diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-25 13:17:42 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-27 09:54:24 +0100 |
commit | c6c34db202ce504cff1e6cc71d9f809a8365e066 (patch) | |
tree | 30c8189d3da95db1a0c831855723db5624990a4a /src/qml/qml/qqmlvmemetaobject.cpp | |
parent | e80067f2651a00f3d164aa4eba863141b281e740 (diff) |
QQmlVMEMetaObject: Don't use QQmlListProperty's reserved fields
The object carries a reference to the metaObject anyway, and the id can
be used to retrieve the list. There is no need to meddle with dummy1 and
dummy2.
Task-number: QTBUG-79263
Change-Id: If2d4130b9d53da680352c756d8aa5977504207dc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlvmemetaobject.cpp')
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 75 |
1 files changed, 58 insertions, 17 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index de3889f1c1..e0ca1ae6c5 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -62,30 +62,73 @@ QT_BEGIN_NAMESPACE +class ResolvedList +{ + Q_DISABLE_COPY_MOVE(ResolvedList) + +public: + ResolvedList(QQmlListProperty<QObject> *prop) : + m_metaObject(static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(prop->object)->metaObject)), + m_id(quintptr(prop->data)) + { + Q_ASSERT(m_metaObject); + Q_ASSERT(m_metaObject->object == prop->object); + Q_ASSERT(m_id <= quintptr(std::numeric_limits<int>::max() - m_metaObject->methodOffset())); + + // readPropertyAsList() with all the checks transformed into Q_ASSERT + // and without allocation. + Q_ASSERT(!m_metaObject->propertyAndMethodStorage.isUndefined()); + auto *md = static_cast<QV4::MemberData *>(m_metaObject->propertyAndMethodStorage.asManaged()); + Q_ASSERT(md); + const auto *v = (md->data() + m_id)->as<QV4::VariantObject>(); + Q_ASSERT(v); + Q_ASSERT(v->d()); + QVariant &data = v->d()->data(); + Q_ASSERT(data.userType() == qMetaTypeId<QList<QObject *>>()); + m_list = static_cast<QList<QObject *> *>(data.data()); + Q_ASSERT(m_list); + } + + ~ResolvedList() = default; + + QQmlVMEMetaObject *metaObject() const { return m_metaObject; } + QList<QObject *> *list() const { return m_list; } + quintptr id() const { return m_id; } + + void activateSignal() const + { + m_metaObject->activate(m_metaObject->object, int(m_id + m_metaObject->methodOffset()), + nullptr); + } + +private: + QQmlVMEMetaObject *m_metaObject = nullptr; + QList<QObject *> *m_list = nullptr; + quintptr m_id = 0; +}; + static void list_append(QQmlListProperty<QObject> *prop, QObject *o) { - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - list->append(o); - static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), nullptr); + const ResolvedList resolved(prop); + resolved.list()->append(o); + resolved.activateSignal(); } static int list_count(QQmlListProperty<QObject> *prop) { - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - return list->count(); + return ResolvedList(prop).list()->count(); } static QObject *list_at(QQmlListProperty<QObject> *prop, int index) { - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - return list->at(index); + return ResolvedList(prop).list()->at(index); } static void list_clear(QQmlListProperty<QObject> *prop) { - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - list->clear(); - static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), nullptr); + const ResolvedList resolved(prop); + resolved.list()->clear(); + resolved.activateSignal(); } QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr() @@ -683,13 +726,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * break; case QV4::CompiledData::BuiltinType::InvalidBuiltin: if (property.isList) { - QList<QObject *> *list = readPropertyAsList(id); - QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]); - *p = QQmlListProperty<QObject>(object, list, - list_append, list_count, list_at, - list_clear); - p->dummy1 = this; - p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id)); + readPropertyAsList(id); // Initializes if necessary + *static_cast<QQmlListProperty<QObject> *>(a[0]) + = QQmlListProperty<QObject>( + object, reinterpret_cast<void *>(quintptr(id)), + list_append, list_count, list_at, list_clear); } else { *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id); } |