From: Simon Hausmann Date: Mon, 12 Dec 2011 12:41:25 +0000 (+0100) Subject: Fix leak of v8 context used for implicit strong references. X-Git-Tag: qt-v5.0.0-alpha1~851 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f12d2a28d799e95661a50ee70d4c9059377fbfc1;p=profile%2Fivi%2Fqtdeclarative.git Fix leak of v8 context used for implicit strong references. QV8GCCallback::Referencer keeps strong implicit references for QObjects owned by C++ (or objects with a CPP owned root parent). The implicit v8 object to express the implicit reference belongs to a dedicated v8 context, which needs to be disposed properly. Change-Id: Ic0555cb8d94384a185ebcee9825988d84e74f26b Reviewed-by: Aaron Kennedy Reviewed-by: Chris Adams --- diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 632a8ea..5207931 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -1451,14 +1451,6 @@ void QV8GCCallback::registerGcPrologueCallback() } } -void QV8GCCallback::ThreadData::releaseStrongReferencer() -{ - // NOTE: must be called with a valid current isolate - if (!referencer.strongReferencer.IsEmpty()) { - qPersistentDispose(referencer.strongReferencer); - } -} - void QV8GCCallback::releaseWorkerThreadGcPrologueCallbackData() { // Note that only worker-thread implementations with their @@ -1467,7 +1459,7 @@ void QV8GCCallback::releaseWorkerThreadGcPrologueCallbackData() Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8GCCallback::releaseWorkerThreadGcPrologueCallbackData()", "called after v8::Isolate has exited"); if (threadData.hasLocalData()) { QV8GCCallback::ThreadData *td = threadData.localData(); - td->releaseStrongReferencer(); + td->referencer.dispose(); } } @@ -1483,18 +1475,14 @@ QV8GCCallback::Node::~Node() QV8GCCallback::Referencer::~Referencer() { - if (!strongReferencer.IsEmpty()) { - Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8GCCallback::Referencer::~Referencer()", "called after v8::Isolate has exited"); - // automatically release the strongReferencer if it hasn't - // been explicitly released already. - qPersistentDispose(strongReferencer); - } + dispose(); } QV8GCCallback::Referencer::Referencer() { v8::HandleScope handleScope; - v8::Handle context = v8::Context::New(); + context = v8::Context::New(); + qPersistentRegister(context); v8::Context::Scope contextScope(context); strongReferencer = qPersistentNew(v8::Object::New()); } @@ -1511,6 +1499,18 @@ void QV8GCCallback::Referencer::addRelationship(QObject *object, QObject *other) } } +void QV8GCCallback::Referencer::dispose() +{ + if (!strongReferencer.IsEmpty()) { + Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8GCCallback::Referencer::~Referencer()", "called after v8::Isolate has exited"); + // automatically release the strongReferencer if it hasn't + // been explicitly released already. + qPersistentDispose(strongReferencer); + } + if (!context.IsEmpty()) + qPersistentDispose(context); +} + void QV8GCCallback::Referencer::addRelationship(QObject *object, v8::Persistent handle) { if (handle.IsEmpty()) diff --git a/src/declarative/qml/v8/qv8gccallback_p.h b/src/declarative/qml/v8/qv8gccallback_p.h index f18b20b..297ac8a 100644 --- a/src/declarative/qml/v8/qv8gccallback_p.h +++ b/src/declarative/qml/v8/qv8gccallback_p.h @@ -74,10 +74,12 @@ public: ~Referencer(); void addRelationship(QObject *object, v8::Persistent handle); void addRelationship(QObject *object, QObject *other); + void dispose(); private: Referencer(); static v8::Persistent *findOwnerAndStrength(QObject *qobjectOwner, bool *shouldBeStrong); v8::Persistent strongReferencer; + v8::Persistent context; friend class QV8GCCallback::ThreadData; }; @@ -101,7 +103,6 @@ private: Referencer referencer; bool gcPrologueCallbackRegistered; QIntrusiveList gcCallbackNodes; - void releaseStrongReferencer(); }; static void initializeThreadData();