aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/v8/qv8engine.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2011-12-13 17:18:45 +0100
committerQt by Nokia <qt-info@nokia.com>2011-12-15 13:42:29 +0100
commitd70cca804e88110eae32f92baff7cee957a6a531 (patch)
treefa2dc18d907095c8bb953e249cfc2dd379b5bd9c /src/declarative/qml/v8/qv8engine.cpp
parent9ae39c98f43a29e3f68a1f34469c9ad2551f813c (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.cpp153
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();