aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlvmemetaobject.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-11-25 13:17:42 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-11-27 09:54:24 +0100
commitc6c34db202ce504cff1e6cc71d9f809a8365e066 (patch)
tree30c8189d3da95db1a0c831855723db5624990a4a /src/qml/qml/qqmlvmemetaobject.cpp
parente80067f2651a00f3d164aa4eba863141b281e740 (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.cpp75
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);
}