aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/v8/qv8qobjectwrapper.cpp
diff options
context:
space:
mode:
authorJędrzej Nowacki <jedrzej.nowacki@nokia.com>2012-04-19 14:38:38 +0200
committerQt by Nokia <qt-info@nokia.com>2012-04-27 10:38:58 +0200
commitb765e3a84bc531878a5cc0d451451a94565b13f8 (patch)
tree4c506d229c76924a2c72de31464efa8b440f005f /src/qml/qml/v8/qv8qobjectwrapper.cpp
parent7ec674ee9a8e51cb1cb7ef60b1d27845349b8dec (diff)
Avoid calling gc in QQmlEngine destructor.
GC may be expensive. GC call in QQmlEngine doesn't have much sense because V8 will destroy all objects living in a current context. The only problem is that V8 may decide to not invoke weak callbacks which may cause a memory leak. To avoid that we track all QObjects that have JavaScript ownership set and we delete them explicitly. The change reduce time of destroying QQmlEngine by 75%, which is really visible in qquicklistmodel test. Change-Id: I2a3668fd23630669114baee8c241a7ecc4100e33 Reviewed-by: Chris Adams <christopher.adams@nokia.com>
Diffstat (limited to 'src/qml/qml/v8/qv8qobjectwrapper.cpp')
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp56
1 files changed, 30 insertions, 26 deletions
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 70f10b2346..2d6c5ec24a 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -80,16 +80,6 @@ QT_BEGIN_NAMESPACE
// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work
// correctly in a worker thread
-class QV8QObjectResource : public QV8ObjectResource
-{
- V8_RESOURCE_TYPE(QObjectType);
-
-public:
- QV8QObjectResource(QV8Engine *engine, QObject *object);
-
- QQmlGuard<QObject> object;
-};
-
class QV8QObjectInstance : public QQmlGuard<QObject>
{
public:
@@ -223,6 +213,13 @@ void QV8QObjectWrapper::destroy()
qPersistentDispose(m_signalHandlerConstructor);
qPersistentDispose(m_methodConstructor);
qPersistentDispose(m_constructor);
+
+ QIntrusiveList<QV8QObjectResource, &QV8QObjectResource::weakResource>::iterator i = m_javaScriptOwnedWeakQObjects.begin();
+ for (; i != m_javaScriptOwnedWeakQObjects.end(); ++i) {
+ QV8QObjectResource *resource = *i;
+ Q_ASSERT(resource);
+ deleteWeakQObject(resource);
+ }
}
struct ReadAccessor {
@@ -930,25 +927,14 @@ static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8
v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
}
-static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *)
+void QV8QObjectWrapper::WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *wrapper)
{
Q_ASSERT(handle->IsObject());
-
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(handle->ToObject());
-
Q_ASSERT(resource);
- QObject *object = resource->object;
- if (object) {
- QQmlData *ddata = QQmlData::get(object, false);
- if (ddata) {
- ddata->v8object.Clear();
- if (!object->parent() && !ddata->indestructible) {
- ddata->isQueuedForDeletion = true;
- object->deleteLater();
- }
- }
- }
+ static_cast<QV8QObjectWrapper*>(wrapper)->unregisterWeakQObjectReference(resource);
+ static_cast<QV8QObjectWrapper*>(wrapper)->deleteWeakQObject(resource);
qPersistentDispose(handle);
}
@@ -1117,8 +1103,10 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine);
ddata->v8object = qPersistentNew<v8::Object>(rv);
- ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ ddata->v8object.MakeWeak(this, WeakQObjectReferenceCallback);
ddata->v8objectid = m_id;
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(rv);
+ registerWeakQObjectReference(resource);
return rv;
} else {
@@ -1133,8 +1121,10 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
if ((!found || (*iter)->v8object.IsEmpty()) && ddata->v8object.IsEmpty()) {
v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine);
ddata->v8object = qPersistentNew<v8::Object>(rv);
- ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ ddata->v8object.MakeWeak(this, WeakQObjectReferenceCallback);
ddata->v8objectid = m_id;
+ QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(rv);
+ registerWeakQObjectReference(resource);
if (found) {
delete (*iter);
@@ -1157,6 +1147,20 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
return v8::Local<v8::Object>::New((*iter)->v8object);
}
}
+void QV8QObjectWrapper::deleteWeakQObject(QV8QObjectResource *resource)
+{
+ QObject *object = resource->object;
+ if (object) {
+ QQmlData *ddata = QQmlData::get(object, false);
+ if (ddata) {
+ ddata->v8object.Clear();
+ if (!object->parent() && !ddata->indestructible) {
+ ddata->isQueuedForDeletion = true;
+ object->deleteLater();
+ }
+ }
+ }
+}
QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object)
{