diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-05-24 17:12:57 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@digia.com> | 2013-05-24 19:48:37 +0200 |
commit | de6642b1a97840e204f9d45275ca29a859a890d0 (patch) | |
tree | 5936ca3fa90ce9199459e16c0379424923a6ae46 /src/qml/qml/qqmlvmemetaobject.cpp | |
parent | 788252a2e80ef7e27ab1347d998b482091f93863 (diff) |
Implement JS ownership policy for var and variant properties
Instead of a GC callback, let's keep the lifecycle of the var properties and
the QObject wrapped variants in sync with the lifecycle of the JS QObject
wrapper, through a markObjects re-implementation.
handleReferenceManagement test passes now, fixed a few incorrect gc() calls
in there.
Change-Id: I78e8ca700e41bba788b61d3816a77cfb3a7c5e58
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml/qqmlvmemetaobject.cpp')
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 76 |
1 files changed, 28 insertions, 48 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 995b01264f..cec50ddd5b 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -554,7 +554,7 @@ QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o) QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *meta) -: QV8GCCallback::Node(GcPrologueCallback), object(obj), +: object(obj), ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta), hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1), varPropertiesInitialized(false), interceptors(0), v8methods(0) @@ -577,7 +577,10 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, int list_type = qMetaTypeId<QQmlListProperty<QObject> >(); int qobject_type = qMetaTypeId<QObject*>(); int variant_type = qMetaTypeId<QVariant>(); - bool needsGcCallback = (metaData->varPropertyCount > 0); + // Need JS wrapper to ensure variant and var properties are marked. + // ### FIXME: I hope that this can be removed once we have the proper scope chain + // set up and the JS wrappers always exist. + bool needsJSWrapper = (metaData->varPropertyCount > 0); // ### Optimize for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) { @@ -585,20 +588,15 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, if (t == list_type) { listProperties.append(List(methodOffset() + ii, this)); data[ii].setValue(listProperties.count() - 1); - } else if (!needsGcCallback && (t == qobject_type || t == variant_type)) { - needsGcCallback = true; + } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) { + needsJSWrapper = true; } } firstVarPropertyIndex = metaData->propertyCount - metaData->varPropertyCount; - // both var properties and variant properties can keep references to - // other QObjects, and var properties can also keep references to - // JavaScript objects. If we have any properties, we need to hook - // the gc() to ensure that references keep objects alive as needed. - if (needsGcCallback) { - QV8GCCallback::addGcCallbackNode(this); - } + if (needsJSWrapper) + ensureQObjectWrapper(); } QQmlVMEMetaObject::~QQmlVMEMetaObject() @@ -1207,57 +1205,39 @@ bool QQmlVMEMetaObject::ensureVarPropertiesAllocated() return !varProperties.isEmpty(); } -// see also: QV8GCCallback::garbageCollectorPrologueCallback() -void QQmlVMEMetaObject::allocateVarPropertiesArray() +void QQmlVMEMetaObject::ensureQObjectWrapper() { - varProperties = v8::Array::New(metaData->varPropertyCount)->v4Value(); - // ### FIXME -// varProperties.MakeWeak(static_cast<void*>(this), VarPropertiesWeakReferenceCallback); - varPropertiesInitialized = true; -} - -/* - The "var" properties are stored in a v8::Array which will be strong persistent if the object has cpp-ownership - and the root QObject in the parent chain does not have JS-ownership. In the weak persistent handle case, - this callback will dispose the handle when the v8object which owns the lifetime of the var properties array - is cleared as a result of all other handles to that v8object being released. - See QV8GCCallback::garbageCollectorPrologueCallback() for more information. - */ -void QQmlVMEMetaObject::VarPropertiesWeakReferenceCallback(QV4::PersistentValue &object, void* parameter) -{ - // ### FIXME - QQmlVMEMetaObject *vmemo = static_cast<QQmlVMEMetaObject*>(parameter); - Q_ASSERT(vmemo); - object.clear(); - vmemo->varProperties.clear(); + QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine); + QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine(); + v8e->newQObject(object); } -void QQmlVMEMetaObject::GcPrologueCallback(QV8GCCallback::Node *node) +void QQmlVMEMetaObject::mark() { - QQmlVMEMetaObject *vmemo = static_cast<QQmlVMEMetaObject*>(node); - Q_ASSERT(vmemo); - - if (!vmemo->ctxt || !vmemo->ctxt->engine) - return; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(vmemo->ctxt->engine); + varProperties.markOnce(); // add references created by VMEVariant properties - int maxDataIdx = vmemo->metaData->propertyCount - vmemo->metaData->varPropertyCount; + int maxDataIdx = metaData->propertyCount - metaData->varPropertyCount; for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimize? - if (vmemo->data[ii].dataType() == QMetaType::QObjectStar) { + if (data[ii].dataType() == QMetaType::QObjectStar) { // possible QObject reference. - QObject *ref = vmemo->data[ii].asQObject(); + QObject *ref = data[ii].asQObject(); if (ref) { - ep->v8engine()->addRelationshipForGC(vmemo->object, ref); + QQmlData *ddata = QQmlData::get(ref); + if (ddata) + ddata->v8object.markOnce(); } } } +} - // add references created by var properties - if (!vmemo->varPropertiesInitialized || vmemo->varProperties.isEmpty()) - return; +// see also: QV8GCCallback::garbageCollectorPrologueCallback() +void QQmlVMEMetaObject::allocateVarPropertiesArray() +{ + varProperties = v8::Array::New(metaData->varPropertyCount)->v4Value(); // ### FIXME - // ep->v8engine()->addRelationshipForGC(vmemo->object, vmemo->varProperties); +// varProperties.MakeWeak(static_cast<void*>(this), VarPropertiesWeakReferenceCallback); + varPropertiesInitialized = true; } bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const |