diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2011-12-13 17:18:45 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-15 13:42:29 +0100 |
commit | d70cca804e88110eae32f92baff7cee957a6a531 (patch) | |
tree | fa2dc18d907095c8bb953e249cfc2dd379b5bd9c /src/declarative/qml/v8/qv8engine.cpp | |
parent | 9ae39c98f43a29e3f68a1f34469c9ad2551f813c (diff) |
V8: Remove extra V8::Context allocated for expressing strong references
Moved the Referencer code into QV8Engine and re-used the available v8
context there. That also makes things a bit cleaner in the sense that now
references from one object to another are guaranteed to be within the same
context. Previously some strong references would be across contexts that
do not actually share a security token.
Change-Id: I717b27a4d96323feb570023d4d84f2b2176d1a84
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
Diffstat (limited to 'src/declarative/qml/v8/qv8engine.cpp')
-rw-r--r-- | src/declarative/qml/v8/qv8engine.cpp | 153 |
1 files changed, 62 insertions, 91 deletions
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 7c3dc1ddc8..d89326aabe 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -141,6 +141,7 @@ QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership) v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback); QV8GCCallback::registerGcPrologueCallback(); + m_strongReferencer = qPersistentNew(v8::Object::New()); m_stringWrapper.init(); m_contextWrapper.init(this); @@ -177,6 +178,8 @@ QV8Engine::~QV8Engine() invalidateAllValues(); clearExceptions(); + qPersistentDispose(m_strongReferencer); + m_sequenceWrapper.destroy(); m_valueTypeWrapper.destroy(); m_variantWrapper.destroy(); @@ -751,6 +754,37 @@ double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt) return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec()); } +v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, bool *shouldBeStrong) +{ + QObject *parent = object->parent(); + if (!parent) { + // if the object has JS ownership, the object's v8object owns the lifetime of the persistent value. + if (QDeclarativeEngine::objectOwnership(object) == QDeclarativeEngine::JavaScriptOwnership) { + *shouldBeStrong = false; + return &(QDeclarativeData::get(object)->v8object); + } + + // no parent, and has CPP ownership - doesn't have an implicit parent. + *shouldBeStrong = true; + return 0; + } + + // if it is owned by CPP, it's root parent may still be owned by JS. + // in that case, the owner of the persistent handle is the root parent's v8object. + while (parent->parent()) + parent = parent->parent(); + + if (QDeclarativeEngine::objectOwnership(parent) == QDeclarativeEngine::JavaScriptOwnership) { + // root parent is owned by JS. It's v8object owns the persistent value in question. + *shouldBeStrong = false; + return &(QDeclarativeData::get(parent)->v8object); + } else { + // root parent has CPP ownership. The persistent value should not be made weak. + *shouldBeStrong = true; + return 0; + } +} + QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate) { // from QScriptEngine::MsToDateTime() @@ -769,6 +803,32 @@ QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate) return convertedUTC.toLocalTime(); } +void QV8Engine::addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle) +{ + if (handle.IsEmpty()) + return; + + bool handleShouldBeStrong = false; + v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); + if (handleShouldBeStrong) { + v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1); + } else if (!implicitOwner->IsEmpty()) { + v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); + } +} + +void QV8Engine::addRelationshipForGC(QObject *object, QObject *other) +{ + bool handleShouldBeStrong = false; + v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); + v8::Persistent<v8::Value> handle = QDeclarativeData::get(other, true)->v8object; + if (handleShouldBeStrong) { + v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1); + } else if (!implicitOwner->IsEmpty()) { + v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); + } +} + static QThreadStorage<QV8Engine::ThreadData*> perThreadEngineData; bool QV8Engine::hasThreadData() @@ -1456,8 +1516,6 @@ void QV8GCCallback::registerGcPrologueCallback() QV8Engine::ThreadData *td = QV8Engine::threadData(); if (!td->gcPrologueCallbackRegistered) { td->gcPrologueCallbackRegistered = true; - if (!td->referencer) - td->referencer = new QV8GCCallback::Referencer; v8::V8::AddGCPrologueCallback(QV8GCCallback::garbageCollectorPrologueCallback, v8::kGCTypeMarkSweepCompact); } } @@ -1472,89 +1530,6 @@ QV8GCCallback::Node::~Node() node.remove(); } -QV8GCCallback::Referencer::~Referencer() -{ - dispose(); -} - -QV8GCCallback::Referencer::Referencer() -{ - v8::HandleScope handleScope; - context = v8::Context::New(); - qPersistentRegister(context); - v8::Context::Scope contextScope(context); - strongReferencer = qPersistentNew(v8::Object::New()); -} - -void QV8GCCallback::Referencer::addRelationship(QObject *object, QObject *other) -{ - bool handleShouldBeStrong = false; - v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); - v8::Persistent<v8::Value> handle = QDeclarativeData::get(other, true)->v8object; - if (handleShouldBeStrong) { - v8::V8::AddImplicitReferences(strongReferencer, &handle, 1); - } else if (!implicitOwner->IsEmpty()) { - v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); - } -} - -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<v8::Value> handle) -{ - if (handle.IsEmpty()) - return; - - bool handleShouldBeStrong = false; - v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); - if (handleShouldBeStrong) { - v8::V8::AddImplicitReferences(strongReferencer, &handle, 1); - } else if (!implicitOwner->IsEmpty()) { - v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); - } -} - -v8::Persistent<v8::Object> *QV8GCCallback::Referencer::findOwnerAndStrength(QObject *object, bool *shouldBeStrong) -{ - QObject *parent = object->parent(); - if (!parent) { - // if the object has JS ownership, the object's v8object owns the lifetime of the persistent value. - if (QDeclarativeEngine::objectOwnership(object) == QDeclarativeEngine::JavaScriptOwnership) { - *shouldBeStrong = false; - return &(QDeclarativeData::get(object)->v8object); - } - - // no parent, and has CPP ownership - doesn't have an implicit parent. - *shouldBeStrong = true; - return 0; - } - - // if it is owned by CPP, it's root parent may still be owned by JS. - // in that case, the owner of the persistent handle is the root parent's v8object. - while (parent->parent()) - parent = parent->parent(); - - if (QDeclarativeEngine::objectOwnership(parent) == QDeclarativeEngine::JavaScriptOwnership) { - // root parent is owned by JS. It's v8object owns the persistent value in question. - *shouldBeStrong = false; - return &(QDeclarativeData::get(parent)->v8object); - } else { - // root parent has CPP ownership. The persistent value should not be made weak. - *shouldBeStrong = true; - return 0; - } -} - /* Ensure that each persistent handle is strong if it has CPP ownership and has no implicitly JS owned object owner in its parent chain, and @@ -1574,14 +1549,13 @@ void QV8GCCallback::garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackF return; QV8Engine::ThreadData *td = QV8Engine::threadData(); - Q_ASSERT(td->referencer); QV8GCCallback::Node *currNode = td->gcCallbackNodes.first(); while (currNode) { // The client which adds itself to the list is responsible // for maintaining the correct implicit references in the // specified callback. - currNode->prologueCallback(td->referencer, currNode); + currNode->prologueCallback(currNode); currNode = td->gcCallbackNodes.next(currNode); } } @@ -1593,8 +1567,7 @@ void QV8GCCallback::addGcCallbackNode(QV8GCCallback::Node *node) } QV8Engine::ThreadData::ThreadData() - : referencer(0) - , gcPrologueCallbackRegistered(false) + : gcPrologueCallbackRegistered(false) { if (!v8::Isolate::GetCurrent()) { isolate = v8::Isolate::New(); @@ -1606,8 +1579,6 @@ QV8Engine::ThreadData::ThreadData() QV8Engine::ThreadData::~ThreadData() { - delete referencer; - referencer = 0; if (isolate) { isolate->Exit(); isolate->Dispose(); |