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>
This commit is contained in:
Erik Verbruggen 2016-09-07 13:31:14 +02:00 committed by Erik Verbruggen
parent 480037f298
commit c08423ac01
12 changed files with 135 additions and 52 deletions

View File

@ -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);

View File

@ -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);
};

View File

@ -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);

View File

@ -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

View File

@ -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));
}

View File

@ -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)

View File

@ -71,7 +71,7 @@ struct QmlContextWrapper : Object {
bool isNullWrapper;
QQmlGuardedContextData context;
QPointer<QObject> scopeObject;
QQmlQPointer<QObject> scopeObject;
};
}

View File

@ -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)

View File

@ -68,7 +68,7 @@ namespace Heap {
struct QmlListWrapper : Object {
QmlListWrapper();
~QmlListWrapper();
QPointer<QObject> object;
QQmlQPointer<QObject> object;
QQmlListProperty<QObject> property;
int propertyType;
};

View File

@ -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

View File

@ -74,7 +74,7 @@ struct QmlTypeWrapper : Object {
QmlTypeWrapper();
~QmlTypeWrapper();
TypeNameMode mode;
QPointer<QObject> object;
QQmlQPointer<QObject> object;
QQmlType *type;
QQmlTypeNameCache *typeNamespace;

View File

@ -63,8 +63,9 @@ namespace Heap {
struct QQmlValueTypeReference : QQmlValueTypeWrapper
{
QQmlValueTypeReference() {}
QPointer<QObject> object;
QQmlValueTypeReference() { object.init(); }
~QQmlValueTypeReference() { object.destroy(); }
QQmlQPointer<QObject> object;
int property;
};