aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-08-24 14:52:30 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2020-08-28 13:49:14 +0200
commit229987d91505203e5a1577651b65880e58239ac7 (patch)
tree4a42a347a831824d2ffc8f8dee6a90a0dd7d0859 /src/qml/qml
parent2afed94c70913e018198422ef222c9168326d09c (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.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp36
-rw-r--r--src/qml/qml/qqmlmetatype_p.h52
-rw-r--r--src/qml/qml/qqmltypedata.cpp12
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;