From d40b206b734ca001819129b92ff270bfe2ea1942 Mon Sep 17 00:00:00 2001 From: Frank Meerkoetter Date: Mon, 20 Jul 2015 22:06:40 +0200 Subject: Port QObject* away from QQmlVMEVariant QObjects are now stored as QV4::QObjectWrapper in a javascript array. This is part of a series of patches slimming down the memory usage of QML properties. Change-Id: I270831d0f0f7bc17842cd2f8d2eb9661e09a3364 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlvmemetaobject.cpp | 70 ++++++++++++++++++++++++++++----------- src/qml/qml/qqmlvmemetaobject_p.h | 4 ++- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 1e60b593f1..39ddaa5e32 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -691,6 +691,27 @@ void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v) vp->putIndexed(id, sv); } +void QQmlVMEMetaObject::writeProperty(int id, QObject* v) +{ + if (!ensurePropertiesAllocated()) + return; + + QV4::Scope scope(properties.engine()); + QV4::ScopedObject vp(scope, properties.value()); + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(ctxt->engine); + QV4::ExecutionEngine *v4 = ep->v4engine(); + vp->putIndexed(id, QV4::ScopedObject(scope, QV4::QObjectWrapper::wrap(v4, v))); + + QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id); + if (v && !guard) { + guard = new QQmlVMEVariantQObjectPtr(true); + varObjectGuards.append(guard); + } + if (guard) + guard->setGuardedValue(v, this, id); +} + int QQmlVMEMetaObject::readPropertyAsInt(int id) { if (!ensurePropertiesAllocated()) @@ -831,6 +852,22 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id) return v->d()->data.value(); } +QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id) +{ + if (!ensurePropertiesAllocated()) + return 0; + + QV4::Scope scope(properties.engine()); + QV4::ScopedObject vp(scope, properties.value()); + QV4::ScopedValue sv(scope, vp->getIndexed(id)); + const QV4::QObjectWrapper *wrapper = sv->as(); + if (!wrapper) { + writeProperty(id, static_cast(Q_NULLPTR)); + return 0; + } + return wrapper->object(); +} + QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) { if (!ensurePropertiesAllocated()) @@ -983,7 +1020,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) *reinterpret_cast(a[0]) = readPropertyAsPointF(id); break; case QMetaType::QObjectStar: - *reinterpret_cast(a[0]) = data[id].asQObject(); + *reinterpret_cast(a[0]) = readPropertyAsQObject(id); break; case QMetaType::QVariant: *reinterpret_cast(a[0]) = readPropertyAsVariant(id); @@ -1045,8 +1082,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) writeProperty(id, *reinterpret_cast(a[0])); break; case QMetaType::QObjectStar: - needActivate = *reinterpret_cast(a[0]) != data[id].asQObject(); - data[id].setValue(*reinterpret_cast(a[0]), this, id); + needActivate = *reinterpret_cast(a[0]) != readPropertyAsQObject(id); + writeProperty(id, *reinterpret_cast(a[0])); break; case QMetaType::QVariant: writeProperty(id, *reinterpret_cast(a[0])); @@ -1230,11 +1267,16 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) } return QVariant(); } else { - if (data[id].dataType() == QMetaType::QObjectStar) { - return QVariant::fromValue(data[id].asQObject()); - } else { - return data[id].asQVariant(); + if (ensurePropertiesAllocated()) { + QV4::ExecutionEngine *v4 = properties.engine(); + QV4::Scope scope(v4); + QV4::ScopedObject o(scope, properties.value()); + QV4::ScopedValue sv(scope, o->getIndexed(id)); + const QV4::QObjectWrapper *wrapper = sv->as(); + if (wrapper) + return QVariant::fromValue(wrapper->object()); } + return data[id].asQVariant(); } } @@ -1313,8 +1355,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) bool needActivate = false; if (value.userType() == QMetaType::QObjectStar) { QObject *o = *(QObject *const *)value.data(); - needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o); - data[id].setValue(o, this, id); + needActivate = readPropertyAsQObject(id) != o; // TODO: still correct? + writeProperty(id, o); } else { needActivate = (data[id].dataType() != qMetaTypeId() || data[id].asQVariant().userType() != value.userType() || @@ -1457,16 +1499,6 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) properties.markOnce(e); - // add references created by VMEVariant properties - int maxDataIdx = metaData->propertyCount - metaData->varPropertyCount; - for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimize? - if (data[ii].dataType() == QMetaType::QObjectStar) { - // possible QObject reference. - if (QObject *ref = data[ii].asQObject()) - QV4::QObjectWrapper::markWrapper(ref, e); - } - } - if (QQmlVMEMetaObject *parent = parentVMEMetaObject()) parent->mark(e); } diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 96b606203a..7009b47a5f 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -142,7 +142,7 @@ public: inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index); QQmlVMEMetaObject *m_target; - unsigned m_isVar : 1; + unsigned m_isVar : 1; // TODO: remove? int m_index : 31; }; @@ -214,6 +214,7 @@ public: QDate readPropertyAsDate(int id); QDateTime readPropertyAsDateTime(int id); QRectF readPropertyAsRectF(int id); + QObject* readPropertyAsQObject(int id); void writeProperty(int id, int v); void writeProperty(int id, bool v); @@ -225,6 +226,7 @@ public: void writeProperty(int id, const QDate& v); void writeProperty(int id, const QDateTime& v); void writeProperty(int id, const QRectF& v); + void writeProperty(int id, QObject *v); void ensureQObjectWrapper(); -- cgit v1.2.3