aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlvmemetaobject.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-05-24 17:12:57 +0200
committerLars Knoll <lars.knoll@digia.com>2013-05-24 19:48:37 +0200
commitde6642b1a97840e204f9d45275ca29a859a890d0 (patch)
tree5936ca3fa90ce9199459e16c0379424923a6ae46 /src/qml/qml/qqmlvmemetaobject.cpp
parent788252a2e80ef7e27ab1347d998b482091f93863 (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.cpp76
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