diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-09-07 13:31:14 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-09-27 08:37:39 +0000 |
commit | c08423ac01be53a40226b30e62d2d50d1fca9fd5 (patch) | |
tree | bf5803dcfd215b3f53f18e0479971cb2a4d3b5ad | |
parent | 480037f2988f5b3010bd6a444cda8e28a24571fd (diff) |
QML: Replace QPointer with a QQmlQPointer (which is trivial)
One of the steps needed to make QV4::Heap::structs trivial.
Change-Id: Ic4d73f15035af21c8a682aaad1ee68cdd91f8e7d
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 72 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper_p.h | 28 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 9 | ||||
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 56 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontextwrapper.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontextwrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmllistwrapper.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmllistwrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 5 |
12 files changed, 135 insertions, 52 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 56d7ea0a59..202b7d3525 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -196,8 +196,8 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object } Heap::QObjectWrapper::QObjectWrapper(QObject *object) - : object(object) { + qObj.init(object); } void QObjectWrapper::initializeBindings(ExecutionEngine *engine) @@ -210,21 +210,21 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont { Q_UNUSED(revisionMode); - QQmlData *ddata = QQmlData::get(d()->object, false); + QQmlData *ddata = QQmlData::get(d()->object(), false); if (!ddata) return 0; QQmlPropertyData *result = 0; if (ddata && ddata->propertyCache) - result = ddata->propertyCache->property(name, d()->object, qmlContext); + result = ddata->propertyCache->property(name, d()->object(), qmlContext); else - result = QQmlPropertyCache::property(engine->jsEngine(), d()->object, name, qmlContext, *local); + result = QQmlPropertyCache::property(engine->jsEngine(), d()->object(), name, qmlContext, *local); return result; } ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, bool includeImports) const { - if (QQmlData::wasDeleted(d()->object)) { + if (QQmlData::wasDeleted(d()->object())) { if (hasProperty) *hasProperty = false; return QV4::Encode::undefined(); @@ -237,7 +237,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String if (hasProperty) *hasProperty = true; ExecutionContext *global = v4->rootContext(); - return QV4::QObjectMethod::create(global, d()->object, index); + return QV4::QObjectMethod::create(global, d()->object(), index); } QQmlPropertyData local; @@ -256,10 +256,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String if (r.scriptIndex != -1) { return QV4::Encode::undefined(); } else if (r.type) { - return QmlTypeWrapper::create(v4, d()->object, + return QmlTypeWrapper::create(v4, d()->object(), r.type, Heap::QmlTypeWrapper::ExcludeEnums); } else if (r.importNamespace) { - return QmlTypeWrapper::create(v4, d()->object, + return QmlTypeWrapper::create(v4, d()->object(), qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums); } Q_ASSERT(!"Unreachable"); @@ -269,7 +269,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String return QV4::Object::get(this, name, hasProperty); } - QQmlData *ddata = QQmlData::get(d()->object, false); + QQmlData *ddata = QQmlData::get(d()->object(), false); if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) { if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) { @@ -282,7 +282,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String if (hasProperty) *hasProperty = true; - return getProperty(v4, d()->object, result); + return getProperty(v4, d()->object(), result); } ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired) @@ -577,7 +577,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value) { - setProperty(engine, d()->object, propertyIndex, value); + setProperty(engine, d()->object(), propertyIndex, value); } void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value) @@ -630,12 +630,12 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value) QObjectWrapper *that = static_cast<QObjectWrapper*>(m); ExecutionEngine *v4 = that->engine(); - if (v4->hasException || QQmlData::wasDeleted(that->d()->object)) + if (v4->hasException || QQmlData::wasDeleted(that->d()->object())) return; QQmlContextData *qmlContext = v4->callingQmlContext(); - if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) { - QQmlData *ddata = QQmlData::get(that->d()->object); + if (!setQmlProperty(v4, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) { + QQmlData *ddata = QQmlData::get(that->d()->object()); // Types created by QML are not extensible at run-time, but for other QObjects we can store them // as regular JavaScript properties, like on JavaScript objects. if (ddata && ddata->context) { @@ -673,8 +673,8 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name QObjectWrapper *that = static_cast<QObjectWrapper*>(m); - if (that->d()->object) { - const QMetaObject *mo = that->d()->object->metaObject(); + if (that->d()->object()) { + const QMetaObject *mo = that->d()->object()->metaObject(); // These indices don't apply to gadgets, so don't block them. const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject; const int propertyCount = mo->propertyCount(); @@ -944,7 +944,7 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e) { QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that); - if (QObject *o = This->object.data()) { + if (QObject *o = This->object()) { QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o); if (vme) vme->mark(e); @@ -966,18 +966,18 @@ void QObjectWrapper::destroyObject(bool lastCall) if (!h->internalClass) return; // destroyObject already got called - if (h->object) { - QQmlData *ddata = QQmlData::get(h->object, false); + if (h->object()) { + QQmlData *ddata = QQmlData::get(h->object(), false); if (ddata) { - if (!h->object->parent() && !ddata->indestructible) { + if (!h->object()->parent() && !ddata->indestructible) { if (ddata && ddata->ownContext && ddata->context) ddata->context->emitDestruction(); // This object is notionally destroyed now ddata->isQueuedForDeletion = true; if (lastCall) - delete h->object; + delete h->object(); else - h->object->deleteLater(); + h->object()->deleteLater(); } } } @@ -1677,7 +1677,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in { Scope valueScope(scope); Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope)); - method->d()->object = object; + method->d()->setObject(object); if (QQmlData *ddata = QQmlData::get(object)) method->d()->propertyCache = ddata->propertyCache; @@ -1705,7 +1705,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject() { if (propertyCache) return propertyCache->createMetaObject(); - return object->metaObject(); + return object()->metaObject(); } QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const @@ -1714,10 +1714,10 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co if (const QMetaObject *metaObject = d()->metaObject()) { result += QString::fromUtf8(metaObject->className()) + - QLatin1String("(0x") + QString::number((quintptr)d()->object.data(),16); + QLatin1String("(0x") + QString::number((quintptr)d()->object(),16); - if (d()->object) { - QString objectName = d()->object->objectName(); + if (d()->object()) { + QString objectName = d()->object()->objectName(); if (!objectName.isEmpty()) result += QLatin1String(", \"") + objectName + QLatin1Char('\"'); } @@ -1732,9 +1732,9 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const { - if (!d()->object) + if (!d()->object()) return Encode::undefined(); - if (QQmlData::keepAliveDuringGarbageCollection(d()->object)) + if (QQmlData::keepAliveDuringGarbageCollection(d()->object())) return ctx->engine()->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object")); int delay = 0; @@ -1742,9 +1742,9 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con delay = args[0].toUInt32(); if (delay > 0) - QTimer::singleShot(delay, d()->object, SLOT(deleteLater())); + QTimer::singleShot(delay, d()->object(), SLOT(deleteLater())); else - d()->object->deleteLater(); + d()->object()->deleteLater(); return Encode::undefined(); } @@ -1769,8 +1769,8 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const return; } - QQmlObjectOrGadget object(d()->object.data()); - if (!d()->object) { + QQmlObjectOrGadget object(d()->object()); + if (!d()->object()) { if (!d()->valueTypeWrapper) { scope.result = Encode::undefined(); return; @@ -1789,7 +1789,7 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const } method = *data; } else { - const QMetaObject *mo = d()->object->metaObject(); + const QMetaObject *mo = d()->object()->metaObject(); const QMetaMethod moMethod = mo->method(d()->index); method.load(moMethod); @@ -2014,9 +2014,9 @@ DEFINE_OBJECT_VTABLE(QMetaObjectWrapper); Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex) - : object(object) - , signalIndex(signalIndex) + : signalIndex(signalIndex) { + setObject(object); } DEFINE_OBJECT_VTABLE(QmlSignalHandler); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index f0dbd82a63..076f304fea 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -79,18 +79,28 @@ struct QQmlValueTypeWrapper; struct QObjectWrapper : Object { QObjectWrapper(QObject *object); - QPointer<QObject> object; + ~QObjectWrapper() { qObj.destroy(); } + + QObject *object() const { return qObj.data(); } + +private: + QQmlQPointer<QObject> qObj; }; struct QObjectMethod : FunctionObject { QObjectMethod(QV4::ExecutionContext *scope); - QPointer<QObject> object; + ~QObjectMethod() { qObj.destroy(); } QQmlRefPointer<QQmlPropertyCache> propertyCache; int index; Pointer<QQmlValueTypeWrapper> valueTypeWrapper; const QMetaObject *metaObject(); + QObject *object() const { return qObj.data(); } + void setObject(QObject *o) { qObj = o; } + +private: + QQmlQPointer<QObject> qObj; }; struct QMetaObjectWrapper : FunctionObject { @@ -105,8 +115,14 @@ struct QMetaObjectWrapper : FunctionObject { struct QmlSignalHandler : Object { QmlSignalHandler(QObject *object, int signalIndex); - QPointer<QObject> object; + ~QmlSignalHandler() { qObj.destroy(); } int signalIndex; + + QObject *object() const { return qObj.data(); } + void setObject(QObject *o) { qObj = o; } + +private: + QQmlQPointer<QObject> qObj; }; } @@ -119,7 +135,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object static void initializeBindings(ExecutionEngine *engine); - QObject *object() const { return d()->object.data(); } + QObject *object() const { return d()->object(); } ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false) const; static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0); @@ -189,7 +205,7 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index); int methodIndex() const { return d()->index; } - QObject *object() const { return d()->object.data(); } + QObject *object() const { return d()->object(); } QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const; QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const; @@ -230,7 +246,7 @@ struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object V4_NEEDS_DESTROY int signalIndex() const { return d()->signalIndex; } - QObject *object() const { return d()->object.data(); } + QObject *object() const { return d()->object(); } static void initProto(ExecutionEngine *v4); }; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index b15ac7eb5e..59086c245c 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -218,9 +218,10 @@ template <typename Container> struct QQmlSequence : Object { QQmlSequence(const Container &container); QQmlSequence(QObject *object, int propertyIndex); + ~QQmlSequence() { object.destroy(); } mutable Container container; - QPointer<QObject> object; + QQmlQPointer<QObject> object; int propertyIndex; bool isReference; }; @@ -558,6 +559,8 @@ Heap::QQmlSequence<Container>::QQmlSequence(const Container &container) , propertyIndex(-1) , isReference(false) { + object.init(); + QV4::Scope scope(internalClass->engine); QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this); o->setArrayType(Heap::ArrayData::Custom); @@ -566,10 +569,10 @@ Heap::QQmlSequence<Container>::QQmlSequence(const Container &container) template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex) - : object(object) - , propertyIndex(propertyIndex) + : propertyIndex(propertyIndex) , isReference(true) { + this->object.init(object); QV4::Scope scope(internalClass->engine); QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this); o->setArrayType(Heap::ArrayData::Custom); diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index ed7a531766..584e8293e5 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -52,6 +52,7 @@ #include <QtCore/QString> #include <private/qv4global_p.h> +#include <QSharedPointer> QT_BEGIN_NAMESPACE @@ -139,6 +140,61 @@ struct Pointer { } +#ifdef QT_NO_QOBJECT +template <class T> +struct QQmlQPointer { +}; +#else +template <class T> +struct QQmlQPointer { + void init() + { + d = nullptr; + qObject = nullptr; + } + + void init(T *o) + { + Q_ASSERT(d == nullptr); + Q_ASSERT(qObject == nullptr); + if (o) { + d = QtSharedPointer::ExternalRefCountData::getAndRef(o); + qObject = o; + } + } + + void destroy() + { + if (d && !d->weakref.deref()) + delete d; + d = nullptr; + qObject = nullptr; + } + + T *data() const { + return d == nullptr || d->strongref.load() == 0 ? nullptr : qObject; + } + operator T*() const { return data(); } + inline T* operator->() const { return data(); } + QQmlQPointer &operator=(T *o) + { + if (d) + destroy(); + init(o); + return *this; + } + bool isNull() const Q_DECL_NOTHROW + { + return d == nullptr || qObject == nullptr || d->strongref.load() == 0; + } + +private: + QtSharedPointer::ExternalRefCountData *d; + QObject *qObject; +}; +Q_STATIC_ASSERT(std::is_trivial<QQmlQPointer<QObject>>::value); +#endif + } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 5a440bdaf4..337b15d35c 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1059,8 +1059,9 @@ namespace Heap { struct QmlIncubatorObject : Object { QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); + ~QmlIncubatorObject() { parent.destroy(); } QScopedPointer<QQmlComponentIncubator> incubator; - QPointer<QObject> parent; + QQmlQPointer<QObject> parent; QV4::Value valuemap; QV4::Value statusChanged; Pointer<Heap::QmlContext> qmlContext; @@ -1488,6 +1489,7 @@ QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode , statusChanged(QV4::Primitive::undefinedValue()) , qmlContext(0) { + parent.init(); incubator.reset(new QQmlComponentIncubator(this, m)); } diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 2d0ebad764..13d708bc17 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -66,14 +66,15 @@ Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *sc , ownsContext(ownsContext) , isNullWrapper(false) , context(context) - , scopeObject(scopeObject) { + this->scopeObject.init(scopeObject); } Heap::QmlContextWrapper::~QmlContextWrapper() { if (context && ownsContext) context->destroy(); + scopeObject.destroy(); } ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *ctxt, QObject *scope) diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index ca7fcf1d75..2b8c16f274 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -71,7 +71,7 @@ struct QmlContextWrapper : Object { bool isNullWrapper; QQmlGuardedContextData context; - QPointer<QObject> scopeObject; + QQmlQPointer<QObject> scopeObject; }; } diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 5c35866274..425a720867 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -54,6 +54,7 @@ DEFINE_OBJECT_VTABLE(QmlListWrapper); Heap::QmlListWrapper::QmlListWrapper() { + object.init(); QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->setArrayType(Heap::ArrayData::Custom); @@ -61,6 +62,7 @@ Heap::QmlListWrapper::QmlListWrapper() Heap::QmlListWrapper::~QmlListWrapper() { + object.destroy(); } ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, int propType) diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index 26e1e5faaf..1107b957c9 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -68,7 +68,7 @@ namespace Heap { struct QmlListWrapper : Object { QmlListWrapper(); ~QmlListWrapper(); - QPointer<QObject> object; + QQmlQPointer<QObject> object; QQmlListProperty<QObject> property; int propertyType; }; diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 7892555f08..28c2588117 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -58,12 +58,14 @@ DEFINE_OBJECT_VTABLE(QmlTypeWrapper); Heap::QmlTypeWrapper::QmlTypeWrapper() : mode(IncludeEnums) { + object.init(); } Heap::QmlTypeWrapper::~QmlTypeWrapper() { if (typeNamespace) typeNamespace->release(); + object.destroy(); } bool QmlTypeWrapper::isSingleton() const diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 8216526cb5..7c5105b184 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -74,7 +74,7 @@ struct QmlTypeWrapper : Object { QmlTypeWrapper(); ~QmlTypeWrapper(); TypeNameMode mode; - QPointer<QObject> object; + QQmlQPointer<QObject> object; QQmlType *type; QQmlTypeNameCache *typeNamespace; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 2566ab06b5..6b308374e6 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -63,8 +63,9 @@ namespace Heap { struct QQmlValueTypeReference : QQmlValueTypeWrapper { - QQmlValueTypeReference() {} - QPointer<QObject> object; + QQmlValueTypeReference() { object.init(); } + ~QQmlValueTypeReference() { object.destroy(); } + QQmlQPointer<QObject> object; int property; }; |