diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-08-24 14:52:30 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-08-28 13:49:14 +0200 |
commit | 229987d91505203e5a1577651b65880e58239ac7 (patch) | |
tree | 4a42a347a831824d2ffc8f8dee6a90a0dd7d0859 /src/qml/qml | |
parent | 2afed94c70913e018198422ef222c9168326d09c (diff) |
Do proper memory management on the metatype interfaces we create
Those interfaces are always registered in pairs. Add an external
refcount to CompositeMetaTypeIds, and do registration and
de-registration through this class.
Change-Id: I4f3a53ad935a43a734d6506ffc768f507b48ee1f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 36 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 52 | ||||
-rw-r--r-- | src/qml/qml/qqmltypedata.cpp | 12 |
4 files changed, 85 insertions, 19 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 4326002575..f1c79fe8b3 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -649,10 +649,8 @@ QQmlEnginePrivate::~QQmlEnginePrivate() QQmlMetaType::freeUnusedTypesAndCaches(); - for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) { + for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) iter.value()->isRegisteredWithEngine = false; - QQmlMetaType::unregisterInternalCompositeType(iter.value()->typeIds); - } #if QT_CONFIG(qml_debug) delete profiler; #endif diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index cb2522a675..06fdb0fab0 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -54,6 +54,32 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE) QT_BEGIN_NAMESPACE +CompositeMetaTypeIds CompositeMetaTypeIds::fromCompositeName(const QByteArray &name) +{ + auto ids = QQmlMetaType::registerInternalCompositeType(name); + ids.refCount = new int; + *ids.refCount = 1; + return ids; +} + +void CompositeMetaTypeIds::deref() +{ + Q_ASSERT(refCount); + --*refCount; + if (!*refCount) { + delete refCount; + QQmlMetaType::unregisterInternalCompositeType(*this); + refCount = nullptr; + } +} + +CompositeMetaTypeIds::~CompositeMetaTypeIds() +{ + if (refCount) + deref(); +} + + struct LockedData : private QQmlMetaTypeData { friend class QQmlMetaTypeDataPtr; @@ -542,11 +568,11 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit -template <typename T> struct QQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface { const QByteArray name; - QQmlMetaTypeInterface(const QByteArray &name) + template <typename T> + QQmlMetaTypeInterface(const QByteArray &name, T *) : QMetaTypeInterface { /*.revision=*/ 0, /*.alignment=*/ alignof(T), @@ -580,8 +606,8 @@ CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArra QByteArray ptr = className + '*'; QByteArray lst = "QQmlListProperty<" + className + '>'; - QMetaType ptr_type(new QQmlMetaTypeInterface<QObject*>(ptr)); - QMetaType lst_type(new QQmlMetaTypeInterface<QQmlListProperty<QObject>>(lst)); + QMetaType ptr_type(new QQmlMetaTypeInterface(ptr, (QObject **)nullptr)); + QMetaType lst_type(new QQmlMetaTypeInterface(lst, (QQmlListProperty<QObject> *)nullptr)); QQmlMetaTypeDataPtr data; data->qmlLists.insert(lst_type.id(), ptr_type.id()); @@ -593,6 +619,8 @@ void QQmlMetaType::unregisterInternalCompositeType(const CompositeMetaTypeIds &t { QQmlMetaTypeDataPtr data; data->qmlLists.remove(typeIds.listId.id()); + delete static_cast<QQmlMetaTypeInterface *>(QMetaType(typeIds.id).iface()); + delete static_cast<QQmlMetaTypeInterface *>(QMetaType(typeIds.listId).iface()); } int QQmlMetaType::registerUnitCacheHook( diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 58968a1c26..b1fe58af6e 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -66,6 +66,52 @@ namespace QV4 { class ExecutableCompilationUnit; } struct CompositeMetaTypeIds { +private: + int *refCount = nullptr; + void deref(); + void ref() + { + Q_ASSERT(refCount); + ++*refCount; + } +public: + CompositeMetaTypeIds() = default; + CompositeMetaTypeIds(QMetaType id, QMetaType listId) : id(id), listId(listId) {} + CompositeMetaTypeIds(const CompositeMetaTypeIds &other) + : refCount(other.refCount), id(other.id), listId(other.listId) + { + if (refCount) + ref(); + } + CompositeMetaTypeIds(CompositeMetaTypeIds &&other) + : refCount(other.refCount), id(other.id), listId(other.listId) + { + other.refCount = nullptr; + } + CompositeMetaTypeIds &operator=(const CompositeMetaTypeIds &other) + { + if (refCount) + deref(); + refCount = other.refCount; + id = other.id; + listId = other.listId; + if (refCount) + ref(); + return *this; + } + CompositeMetaTypeIds &operator=(CompositeMetaTypeIds &&other) + { + if (refCount) + deref(); + refCount = other.refCount; + id = other.id; + listId = other.listId; + other.refCount = nullptr; + return *this; + } + ~CompositeMetaTypeIds(); + static CompositeMetaTypeIds fromCompositeName(const QByteArray &name); +public: QMetaType id; QMetaType listId; bool isValid() const { return id.isValid() && listId.isValid(); } @@ -73,6 +119,10 @@ struct CompositeMetaTypeIds class Q_QML_PRIVATE_EXPORT QQmlMetaType { + friend struct CompositeMetaTypeIds; + static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className); + static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds); + public: enum class RegistrationResult { Success, @@ -94,8 +144,6 @@ public: static void unregisterType(int type); - static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className); - static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds); static void registerModule(const char *uri, QTypeRevision version); static bool protectModule(const QString &uri, QTypeRevision version, bool protectAllVersions = false); diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index d41685b047..60c56d2b02 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -286,7 +286,7 @@ void setupICs(const ObjectContainer &container, QHash<int, InlineComponentData> auto url = finalUrl; url.setFragment(QString::number(it->objectIndex)); const QByteArray &className = QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(url); - InlineComponentData icDatum(QQmlMetaType::registerInternalCompositeType(className), int(it->objectIndex), int(it->nameIndex), 0, 0, 0); + InlineComponentData icDatum(CompositeMetaTypeIds::fromCompositeName(className), int(it->objectIndex), int(it->nameIndex), 0, 0, 0); icData->insert(it->objectIndex, icDatum); } } @@ -402,21 +402,13 @@ void QQmlTypeData::done() m_typeClassName = QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(finalUrl()); if (!m_typeClassName.isEmpty()) - m_typeIds = QQmlMetaType::registerInternalCompositeType(m_typeClassName); + m_typeIds = CompositeMetaTypeIds::fromCompositeName(m_typeClassName); if (m_document) { setupICs(m_document, &m_inlineComponentData, finalUrl()); } else { setupICs(m_compiledData, &m_inlineComponentData, finalUrl()); } - auto typeCleanupGuard = qScopeGuard([&]() { - if (isError() && m_typeIds.isValid()) { - QQmlMetaType::unregisterInternalCompositeType(m_typeIds); - for (auto&& icData: qAsConst(m_inlineComponentData)) { - QQmlMetaType::unregisterInternalCompositeType(icData.typeIds); - } - } - }); QV4::ResolvedTypeReferenceMap resolvedTypeCache; QQmlRefPointer<QQmlTypeNameCache> typeNameCache; |