diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-06-08 14:32:39 +1000 |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-06-08 14:32:39 +1000 |
commit | 8902609a7e6cc27fceff15aa80547f1137efd7c9 (patch) | |
tree | 5cceabf2176d66260a4e6a600fbdf7c8f4002c80 | |
parent | 96cfe77fa311e60a2dfb7967d7ad6c06d40b99fb (diff) |
Implement global handle tracking
This makes it easier to track down handles that have been double
Dispose()'d. See qv8engine_p.h for details.
19 files changed, 196 insertions, 124 deletions
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 5a241991d0..2b96d8fbc0 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -610,8 +610,9 @@ void QDeclarativeContextData::destroy() if (optimizedBindings) optimizedBindings->release(); - for (int ii = 0; ii < importedScripts.count(); ++ii) - importedScripts[ii].Dispose(); + for (int ii = 0; ii < importedScripts.count(); ++ii) { + qPersistentDispose(importedScripts[ii]); + } delete [] idValues; diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 557bb04bd0..0438d23f52 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -78,10 +78,8 @@ QDeclarativeQtScriptExpression::QDeclarativeQtScriptExpression() QDeclarativeQtScriptExpression::~QDeclarativeQtScriptExpression() { - v8function.Dispose(); - v8qmlscope.Dispose(); - v8function = v8::Persistent<v8::Function>(); - v8qmlscope = v8::Persistent<v8::Function>(); + qPersistentDispose(v8function); + qPersistentDispose(v8qmlscope); if (guardList) { delete [] guardList; guardList = 0; } if (dataRef) dataRef->release(); @@ -116,7 +114,7 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, v8::Hand QDeclarativeAbstractExpression::setContext(ctxt); scopeObject = me; - v8function = v8::Persistent<v8::Function>::New(func); + v8function = qPersistentNew<v8::Function>(func); expressionFunctionMode = ExplicitContext; expressionFunctionValid = true; } @@ -169,8 +167,8 @@ QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObje v8::Local<v8::Object> scopeobject = ep->v8engine.qmlScope(ctxt, scope); v8::Local<v8::Script> script = ep->v8engine.qmlModeCompile(code, filename, line); v8::Local<v8::Value> result = script->Run(scopeobject); - if (qmlscope) *qmlscope = v8::Persistent<v8::Object>::New(scopeobject); - return v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(result)); + if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject); + return qPersistentNew<v8::Function>(v8::Local<v8::Function>::Cast(result)); } /*! @@ -353,10 +351,8 @@ void QDeclarativeExpression::setExpression(const QString &expression) d->resetNotifyOnChange(); d->expression = expression; d->expressionFunctionValid = false; - d->v8function.Dispose(); - d->v8qmlscope.Dispose(); - d->v8function = v8::Persistent<v8::Function>(); - d->v8qmlscope = v8::Persistent<v8::Function>(); + qPersistentDispose(d->v8function); + qPersistentDispose(d->v8qmlscope); } void QDeclarativeExpressionPrivate::exceptionToError(v8::Handle<v8::Message> message, diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index b2aad7b7bc..783a66ef97 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -168,8 +168,7 @@ void QDeclarativePropertyCache::clear() indexCache.clear(); methodIndexCache.clear(); stringCache.clear(); - constructor.Dispose(); - constructor.Clear(); + qPersistentDispose(constructor); } QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObject *metaObject, @@ -251,8 +250,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb { Q_UNUSED(revision); - constructor.Dispose(); // Now invalid - constructor.Clear(); + qPersistentDispose(constructor); // Now invalid allowedRevisionCache.append(0); diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index 5ceef36e4b..df072ed02d 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -194,8 +194,8 @@ static void qmlsqldatabase_rows_setForwardOnly(v8::Local<v8::String> property, QDeclarativeSqlDatabaseData::~QDeclarativeSqlDatabaseData() { - constructor.Dispose(); constructor = v8::Persistent<v8::Function>(); - queryConstructor.Dispose(); queryConstructor = v8::Persistent<v8::Function>(); + qPersistentDispose(constructor); + qPersistentDispose(queryConstructor); } static QString qmlsqldatabase_databasesPath(QV8Engine *engine) @@ -526,7 +526,7 @@ QDeclarativeSqlDatabaseData::QDeclarativeSqlDatabaseData(QV8Engine *engine) ft->PrototypeTemplate()->SetAccessor(v8::String::New("version"), qmlsqldatabase_version); ft->PrototypeTemplate()->Set(v8::String::New("changeVersion"), V8FUNCTION(qmlsqldatabase_changeVersion, engine)); - constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } { @@ -534,7 +534,7 @@ QDeclarativeSqlDatabaseData::QDeclarativeSqlDatabaseData(QV8Engine *engine) ft->InstanceTemplate()->SetHasExternalResource(true); ft->PrototypeTemplate()->Set(v8::String::New("executeSql"), V8FUNCTION(qmlsqldatabase_executeSql, engine)); - queryConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + queryConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); } { v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); @@ -544,7 +544,7 @@ QDeclarativeSqlDatabaseData::QDeclarativeSqlDatabaseData(QV8Engine *engine) ft->InstanceTemplate()->SetAccessor(v8::String::New("forwardOnly"), qmlsqldatabase_rows_forwardOnly, qmlsqldatabase_rows_setForwardOnly); ft->InstanceTemplate()->SetIndexedPropertyHandler(qmlsqldatabase_rows_index); - rowsConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + rowsConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); } } diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 68fea5bcd5..b4e6ef4bf1 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -1101,8 +1101,8 @@ void QDeclarativeScriptData::clear() scripts.at(ii)->release(); scripts.clear(); - m_program.Dispose(); - m_value.Dispose(); + qPersistentDispose(m_program); + qPersistentDispose(m_value); } QDeclarativeScriptBlob::QDeclarativeScriptBlob(const QUrl &url, QDeclarativeTypeLoader *loader) @@ -1237,7 +1237,7 @@ void QDeclarativeScriptBlob::done() v8::HandleScope handle_scope; v8::Context::Scope scope(v8engine->context()); v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_source, finalUrl().toString(), 1); - m_scriptData->m_program = v8::Persistent<v8::Script>::New(program); + m_scriptData->m_program = qPersistentNew<v8::Script>(program); } QDeclarativeQmldirData::QDeclarativeQmldirData(const QUrl &url) diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index ffe1e7a165..c99551ff06 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -964,7 +964,7 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script) { if (script->m_loaded) - return v8::Persistent<v8::Object>::New(script->m_value); + return qPersistentNew<v8::Object>(script->m_value); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine); QV8Engine *v8engine = &ep->v8engine; @@ -1015,9 +1015,9 @@ v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentC } } - rv = v8::Persistent<v8::Object>::New(qmlglobal); + rv = qPersistentNew<v8::Object>(qmlglobal); if (shared) { - script->m_value = v8::Persistent<v8::Object>::New(qmlglobal); + script->m_value = qPersistentNew<v8::Object>(qmlglobal); script->m_loaded = true; } diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 97c7754c6f..218b1c1209 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -419,8 +419,9 @@ QDeclarativeVMEMetaObject::~QDeclarativeVMEMetaObject() delete parent; delete [] data; - for (int ii = 0; v8methods && ii < metaData->methodCount; ++ii) - v8methods[ii].Dispose(); + for (int ii = 0; v8methods && ii < metaData->methodCount; ++ii) { + qPersistentDispose(v8methods[ii]); + } } int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) @@ -845,7 +846,7 @@ void QDeclarativeVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Funct int methodIndex = index - methodOffset - plainSignals; if (!v8methods[methodIndex].IsEmpty()) - v8methods[methodIndex].Dispose(); + qPersistentDispose(v8methods[methodIndex]); v8methods[methodIndex] = value; } diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index fd2b924f65..b519573ccf 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -196,8 +196,8 @@ QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QDeclarativeWo QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() { - createsend.Dispose(); createsend.Clear(); - onmessage.Dispose(); onmessage.Clear(); + qPersistentDispose(createsend); + qPersistentDispose(onmessage); delete accessManager; } @@ -229,7 +229,7 @@ void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::init() { v8::Local<v8::Script> onmessagescript = v8::Script::New(v8::String::New(CALL_ONMESSAGE_SCRIPT)); - onmessage = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(onmessagescript->Run())); + onmessage = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(onmessagescript->Run())); } { v8::Local<v8::Script> createsendscript = v8::Script::New(v8::String::New(SEND_MESSAGE_CREATE_SCRIPT)); @@ -240,7 +240,7 @@ void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::init() }; v8::Local<v8::Value> createsendvalue = createsendconstructor->Call(global(), 1, args); - createsend = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(createsendvalue)); + createsend = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(createsendvalue)); } } @@ -301,7 +301,7 @@ v8::Handle<v8::Object> QDeclarativeWorkerScriptEnginePrivate::getWorker(WorkerSc if (!script->initialized) { script->initialized = true; - script->object = v8::Persistent<v8::Object>::New(workerEngine->contextWrapper()->urlScope(script->source)); + script->object = qPersistentNew<v8::Object>(workerEngine->contextWrapper()->urlScope(script->source)); workerEngine->contextWrapper()->setReadOnly(script->object, false); @@ -491,7 +491,7 @@ QDeclarativeWorkerScriptEnginePrivate::WorkerScript::WorkerScript() QDeclarativeWorkerScriptEnginePrivate::WorkerScript::~WorkerScript() { - object.Dispose(); object.Clear(); + qPersistentDispose(object); } int QDeclarativeWorkerScriptEngine::registerWorkerScript(QDeclarativeWorkerScript *owner) diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index 47f0fffa18..22ff4085ad 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -133,16 +133,16 @@ QDeclarativeXMLHttpRequestData::QDeclarativeXMLHttpRequestData() QDeclarativeXMLHttpRequestData::~QDeclarativeXMLHttpRequestData() { - nodeFunction.Dispose(); nodeFunction.Clear(); - namedNodeMapPrototype.Dispose(); namedNodeMapPrototype.Clear(); - nodeListPrototype.Dispose(); nodeListPrototype.Clear(); - nodePrototype.Dispose(); nodePrototype.Clear(); - elementPrototype.Dispose(); elementPrototype.Clear(); - attrPrototype.Dispose(); attrPrototype.Clear(); - characterDataPrototype.Dispose(); characterDataPrototype.Clear(); - textPrototype.Dispose(); textPrototype.Clear(); - cdataPrototype.Dispose(); cdataPrototype.Clear(); - documentPrototype.Dispose(); documentPrototype.Clear(); + qPersistentDispose(nodeFunction); + qPersistentDispose(namedNodeMapPrototype); + qPersistentDispose(nodeListPrototype); + qPersistentDispose(nodePrototype); + qPersistentDispose(elementPrototype); + qPersistentDispose(attrPrototype); + qPersistentDispose(characterDataPrototype); + qPersistentDispose(textPrototype); + qPersistentDispose(cdataPrototype); + qPersistentDispose(documentPrototype); } v8::Local<v8::Object> QDeclarativeXMLHttpRequestData::newNode() @@ -150,7 +150,7 @@ v8::Local<v8::Object> QDeclarativeXMLHttpRequestData::newNode() if (nodeFunction.IsEmpty()) { v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetHasExternalResource(true); - nodeFunction = v8::Persistent<v8::Function>::New(ft->GetFunction()); + nodeFunction = qPersistentNew<v8::Function>(ft->GetFunction()); } return nodeFunction->NewInstance(); @@ -515,7 +515,7 @@ v8::Handle<v8::Object> Node::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->nodePrototype.IsEmpty()) { - d->nodePrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->nodePrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->nodePrototype->SetAccessor(v8::String::New("nodeName"), nodeName, 0, v8::External::Wrap(engine)); d->nodePrototype->SetAccessor(v8::String::New("nodeValue"), nodeValue, @@ -582,7 +582,7 @@ v8::Handle<v8::Object> Element::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->elementPrototype.IsEmpty()) { - d->elementPrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->elementPrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->elementPrototype->SetPrototype(Node::prototype(engine)); d->elementPrototype->SetAccessor(v8::String::New("tagName"), nodeName, 0, v8::External::Wrap(engine)); @@ -595,7 +595,7 @@ v8::Handle<v8::Object> Attr::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->attrPrototype.IsEmpty()) { - d->attrPrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->attrPrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->attrPrototype->SetPrototype(Node::prototype(engine)); d->attrPrototype->SetAccessor(v8::String::New("name"), name, 0, v8::External::Wrap(engine)); @@ -648,7 +648,7 @@ v8::Handle<v8::Object> CharacterData::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->characterDataPrototype.IsEmpty()) { - d->characterDataPrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->characterDataPrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->characterDataPrototype->SetPrototype(Node::prototype(engine)); d->characterDataPrototype->SetAccessor(v8::String::New("data"), nodeValue, 0, v8::External::Wrap(engine)); @@ -681,7 +681,7 @@ v8::Handle<v8::Object> Text::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->textPrototype.IsEmpty()) { - d->textPrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->textPrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->textPrototype->SetPrototype(CharacterData::prototype(engine)); d->textPrototype->SetAccessor(v8::String::New("isElementContentWhitespace"), isElementContentWhitespace, 0, v8::External::Wrap(engine)); @@ -696,7 +696,7 @@ v8::Handle<v8::Object> CDATA::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->cdataPrototype.IsEmpty()) { - d->cdataPrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->cdataPrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->cdataPrototype->SetPrototype(Text::prototype(engine)); // XXX freeze } @@ -707,7 +707,7 @@ v8::Handle<v8::Object> Document::prototype(QV8Engine *engine) { QDeclarativeXMLHttpRequestData *d = xhrdata(engine); if (d->documentPrototype.IsEmpty()) { - d->documentPrototype = v8::Persistent<v8::Object>::New(v8::Object::New()); + d->documentPrototype = qPersistentNew<v8::Object>(v8::Object::New()); d->documentPrototype->SetPrototype(Node::prototype(engine)); d->documentPrototype->SetAccessor(v8::String::New("xmlVersion"), xmlVersion, 0, v8::External::Wrap(engine)); @@ -878,7 +878,7 @@ v8::Handle<v8::Object> NamedNodeMap::prototype(QV8Engine *engine) ot->SetAccessor(v8::String::New("length"), length, 0, v8::External::Wrap(engine)); ot->SetIndexedPropertyHandler(indexed, 0, 0, 0, 0, v8::External::Wrap(engine)); ot->SetFallbackPropertyHandler(named, 0, 0, 0, 0, v8::External::Wrap(engine)); - d->namedNodeMapPrototype = v8::Persistent<v8::Object>::New(ot->NewInstance()); + d->namedNodeMapPrototype = qPersistentNew<v8::Object>(ot->NewInstance()); // XXX freeze } return d->namedNodeMapPrototype; @@ -927,7 +927,7 @@ v8::Handle<v8::Object> NodeList::prototype(QV8Engine *engine) v8::Local<v8::ObjectTemplate> ot = v8::ObjectTemplate::New(); ot->SetAccessor(v8::String::New("length"), length, 0, v8::External::Wrap(engine)); ot->SetIndexedPropertyHandler(indexed, 0, 0, 0, 0, v8::External::Wrap(engine)); - d->nodeListPrototype = v8::Persistent<v8::Object>::New(ot->NewInstance()); + d->nodeListPrototype = qPersistentNew<v8::Object>(ot->NewInstance()); // XXX freeze } return d->nodeListPrototype; @@ -1259,11 +1259,10 @@ v8::Handle<v8::Object> QDeclarativeXMLHttpRequest::getMe() const void QDeclarativeXMLHttpRequest::setMe(v8::Handle<v8::Object> me) { - m_me.Dispose(); - m_me = v8::Persistent<v8::Object>(); + qPersistentDispose(m_me); if (!me.IsEmpty()) - m_me = v8::Persistent<v8::Object>::New(me); + m_me = qPersistentNew<v8::Object>(me); } void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes) diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp index 1af4b4c883..27002c6dc0 100644 --- a/src/declarative/qml/v8/qv8contextwrapper.cpp +++ b/src/declarative/qml/v8/qv8contextwrapper.cpp @@ -123,8 +123,8 @@ QV8ContextWrapper::~QV8ContextWrapper() void QV8ContextWrapper::destroy() { - m_urlConstructor.Dispose(); m_urlConstructor.Clear(); - m_constructor.Dispose(); m_constructor.Clear(); + qPersistentDispose(m_urlConstructor); + qPersistentDispose(m_constructor); } void QV8ContextWrapper::init(QV8Engine *engine) @@ -134,13 +134,13 @@ void QV8ContextWrapper::init(QV8Engine *engine) v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetHasExternalResource(true); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); - m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } { v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetHasExternalResource(true); ft->InstanceTemplate()->SetFallbackPropertyHandler(NullGetter, NullSetter); - m_urlConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_urlConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); } } diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 693c8aa952..530c9b0ef3 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -80,8 +80,7 @@ QV8Engine::~QV8Engine() delete m_listModelData; m_listModelData = 0; - m_getOwnPropertyNames.Dispose(); m_getOwnPropertyNames.Clear(); - + qPersistentDispose(m_getOwnPropertyNames); m_valueTypeWrapper.destroy(); m_variantWrapper.destroy(); m_listWrapper.destroy(); @@ -89,8 +88,7 @@ QV8Engine::~QV8Engine() m_qobjectWrapper.destroy(); m_contextWrapper.destroy(); m_stringWrapper.destroy(); - m_context.Dispose(); - m_context.Clear(); + qPersistentDispose(m_context); } void QV8Engine::init(QDeclarativeEngine *engine) @@ -103,6 +101,7 @@ void QV8Engine::init(QDeclarativeEngine *engine) v8::HandleScope handle_scope; m_context = v8::Context::New(); + qPersistentRegister(m_context); v8::Context::Scope context_scope(m_context); m_stringWrapper.init(); @@ -115,7 +114,7 @@ void QV8Engine::init(QDeclarativeEngine *engine) { v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames")); - m_getOwnPropertyNames = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(v)); + m_getOwnPropertyNames = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(v)); } initializeGlobal(m_context->Global()); @@ -615,6 +614,43 @@ void QV8Engine::gc() while (!v8::V8::IdleNotification()) {} } +#ifdef QML_GLOBAL_HANDLE_DEBUGGING +#include <QtCore/qthreadstorage.h> +static QThreadStorage<QSet<void *> *> QV8Engine_activeHandles; + +void QV8Engine::registerHandle(void *handle) +{ + if (!handle) { + qWarning("Attempting to register a null handle"); + return; + } + + if (!QV8Engine_activeHandles.hasLocalData()) + QV8Engine_activeHandles.setLocalData(new QSet<void *>); + + if (QV8Engine_activeHandles.localData()->contains(handle)) { + qFatal("Handle %p already alive", handle); + } else { + QV8Engine_activeHandles.localData()->insert(handle); + } +} + +void QV8Engine::releaseHandle(void *handle) +{ + if (!handle) + return; + + if (!QV8Engine_activeHandles.hasLocalData()) + QV8Engine_activeHandles.setLocalData(new QSet<void *>); + + if (QV8Engine_activeHandles.localData()->contains(handle)) { + QV8Engine_activeHandles.localData()->remove(handle); + } else { + qFatal("Handle %p already dead", handle); + } +} +#endif + v8::Handle<v8::Value> QV8Engine::gc(const v8::Arguments &args) { gc(); diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h index 5810b3e604..ee0b9115a3 100644 --- a/src/declarative/qml/v8/qv8engine_p.h +++ b/src/declarative/qml/v8/qv8engine_p.h @@ -70,6 +70,13 @@ QT_BEGIN_NAMESPACE + +// Uncomment the following line to enable global handle debugging. When enabled, all the persistent +// handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed +// with qPersistentDispose() are tracked. If you try and do something illegal, like double disposing +// a handle, qFatal() is called. +// #define QML_GLOBAL_HANDLE_DEBUGGING + #define V8_RESOURCE_TYPE(resourcetype) \ public: \ enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \ @@ -240,6 +247,12 @@ public: static void gc(); +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + // Used for handle debugging + static void registerHandle(void *); + static void releaseHandle(void *); +#endif + private: QDeclarativeEngine *m_engine; v8::Persistent<v8::Context> m_context; @@ -294,6 +307,42 @@ private: QDateTime qtDateTimeFromJsDate(double jsDate); }; +// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated +// using this method. +template<class T> +v8::Persistent<T> qPersistentNew(v8::Handle<T> that) +{ + v8::Persistent<T> rv = v8::Persistent<T>::New(that); +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + QV8Engine::registerHandle(*rv); +#endif + return rv; +} + +// Register a Persistent handle that was returned to you by V8 (such as by +// v8::Context::New). This allows us to do handle tracking on these handles too. +template<class T> +void qPersistentRegister(v8::Persistent<T> handle) +{ +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + QV8Engine::registerHandle(*handle); +#else + Q_UNUSED(handle); +#endif +} + +// Dispose and clear a persistent handle. *ALL* persistent handles in QML must be +// disposed using this method. +template<class T> +void qPersistentDispose(v8::Persistent<T> &that) +{ +#ifdef QML_GLOBAL_HANDLE_DEBUGGING + QV8Engine::releaseHandle(*that); +#endif + that.Dispose(); + that.Clear(); +} + QString QV8Engine::toString(v8::Handle<v8::Value> string) { return m_stringWrapper.toString(string->ToString()); diff --git a/src/declarative/qml/v8/qv8include.cpp b/src/declarative/qml/v8/qv8include.cpp index f2b25e0a92..3b8a081a3b 100644 --- a/src/declarative/qml/v8/qv8include.cpp +++ b/src/declarative/qml/v8/qv8include.cpp @@ -54,11 +54,11 @@ QV8Include::QV8Include(const QUrl &url, QV8Engine *engine, QDeclarativeContextDa v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Function> callback) : m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context) { - m_qmlglobal = v8::Persistent<v8::Object>::New(qmlglobal); + m_qmlglobal = qPersistentNew<v8::Object>(qmlglobal); if (!callback.IsEmpty()) - m_callbackFunction = v8::Persistent<v8::Function>::New(callback); + m_callbackFunction = qPersistentNew<v8::Function>(callback); - m_resultObject = v8::Persistent<v8::Object>::New(resultValue()); + m_resultObject = qPersistentNew<v8::Object>(resultValue()); m_network = engine->networkAccessManager(); @@ -72,8 +72,8 @@ QV8Include::QV8Include(const QUrl &url, QV8Engine *engine, QDeclarativeContextDa QV8Include::~QV8Include() { delete m_reply; m_reply = 0; - m_callbackFunction.Dispose(); - m_resultObject.Dispose(); + qPersistentDispose(m_callbackFunction); + qPersistentDispose(m_resultObject); } v8::Local<v8::Object> QV8Include::resultValue(Status status) diff --git a/src/declarative/qml/v8/qv8listwrapper.cpp b/src/declarative/qml/v8/qv8listwrapper.cpp index 9e1110fd85..13b3b30c35 100644 --- a/src/declarative/qml/v8/qv8listwrapper.cpp +++ b/src/declarative/qml/v8/qv8listwrapper.cpp @@ -75,12 +75,12 @@ void QV8ListWrapper::init(QV8Engine *engine) v8::Handle<v8::Value>(), v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } void QV8ListWrapper::destroy() { - m_constructor.Dispose(); + qPersistentDispose(m_constructor); } v8::Handle<v8::Value> QV8ListWrapper::newList(QObject *object, int propId, int propType) diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp index 9ac482e003..75a97ac8b5 100644 --- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp +++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp @@ -93,8 +93,7 @@ public: ~QV8QObjectInstance() { - v8object.Dispose(); - v8object.Clear(); + qPersistentDispose(v8object); } virtual void objectDestroyed(QObject *o) @@ -156,11 +155,11 @@ void QV8QObjectWrapper::destroy() qDeleteAll(m_connections); m_connections.clear(); - m_hiddenObject.Dispose(); m_hiddenObject.Clear(); - m_destroySymbol.Dispose(); m_destroySymbol.Clear(); - m_toStringSymbol.Dispose(); m_toStringSymbol.Clear(); - m_methodConstructor.Dispose(); m_methodConstructor.Clear(); - m_constructor.Dispose(); m_constructor.Clear(); + qPersistentDispose(m_hiddenObject); + qPersistentDispose(m_destroySymbol); + qPersistentDispose(m_toStringSymbol); + qPersistentDispose(m_methodConstructor); + qPersistentDispose(m_constructor); } #define FAST_VALUE_GETTER(name, cpptype, defaultvalue, constructor) \ @@ -204,15 +203,15 @@ void QV8QObjectWrapper::init(QV8Engine *engine) { m_engine = engine; - m_toStringSymbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("toString")); - m_destroySymbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("destroy")); - m_hiddenObject = v8::Persistent<v8::Object>::New(v8::Object::New()); + m_toStringSymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("toString")); + m_destroySymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("destroy")); + m_hiddenObject = qPersistentNew<v8::Object>(v8::Object::New()); { v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator); ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } { v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions @@ -221,7 +220,7 @@ void QV8QObjectWrapper::init(QV8Engine *engine) v8::Handle<v8::Value> invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction(); v8::Handle<v8::Value> args[] = { invokeFn }; v8::Local<v8::Function> createFn = v8::Local<v8::Function>::Cast(fn->Call(engine->global(), 1, args)); - m_methodConstructor = v8::Persistent<v8::Function>::New(createFn); + m_methodConstructor = qPersistentNew<v8::Function>(createFn); } { @@ -656,15 +655,14 @@ static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void } } - handle.Dispose(); + qPersistentDispose(handle); } static void WeakQObjectInstanceCallback(v8::Persistent<v8::Value> handle, void *data) { QV8QObjectInstance *instance = (QV8QObjectInstance *)data; instance->v8object.Clear(); - handle.Dispose(); - handle.Clear(); + qPersistentDispose(handle); } v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8Engine *engine) @@ -735,7 +733,7 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8 } if (ft.IsEmpty()) { - constructor = v8::Persistent<v8::Function>::New(engine->qobjectWrapper()->m_constructor); + constructor = qPersistentNew<v8::Function>(engine->qobjectWrapper()->m_constructor); } else { ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, QV8QObjectWrapper::Setter, @@ -743,7 +741,7 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8 0, QV8QObjectWrapper::Enumerator); ft->InstanceTemplate()->SetHasExternalResource(true); - constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } } @@ -806,7 +804,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object) !ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine); - ddata->v8object = v8::Persistent<v8::Object>::New(rv); + ddata->v8object = qPersistentNew<v8::Object>(rv); ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback); ddata->v8objectid = m_id; return rv; @@ -822,7 +820,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object) // a handle in the ddata, we can assume ownership of the ddata->v8object if ((!found || (*iter)->v8object.IsEmpty()) && ddata->v8object.IsEmpty()) { v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine); - ddata->v8object = v8::Persistent<v8::Object>::New(rv); + ddata->v8object = qPersistentNew<v8::Object>(rv); ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback); ddata->v8objectid = m_id; @@ -840,7 +838,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object) if ((*iter)->v8object.IsEmpty()) { v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine); - (*iter)->v8object = v8::Persistent<v8::Object>::New(rv); + (*iter)->v8object = qPersistentNew<v8::Object>(rv); (*iter)->v8object.MakeWeak((*iter), WeakQObjectInstanceCallback); } @@ -897,10 +895,8 @@ QV8QObjectConnectionList::~QV8QObjectConnectionList() for (SlotHash::Iterator iter = slotHash.begin(); iter != slotHash.end(); ++iter) { QList<Connection> &connections = *iter; for (int ii = 0; ii < connections.count(); ++ii) { - connections[ii].thisObject.Dispose(); - connections[ii].function.Dispose(); - connections[ii].thisObject.Clear(); - connections[ii].function.Clear(); + qPersistentDispose(connections[ii].thisObject); + qPersistentDispose(connections[ii].function); } } slotHash.clear(); @@ -1010,8 +1006,8 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args) QV8QObjectConnectionList::Connection connection; if (!functionThisValue.IsEmpty()) - connection.thisObject = v8::Persistent<v8::Object>::New(functionThisValue->ToObject()); - connection.function = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(functionValue)); + connection.thisObject = qPersistentNew<v8::Object>(functionThisValue->ToObject()); + connection.function = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(functionValue)); slotIter->append(connection); @@ -1084,10 +1080,8 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args) QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function); if (connectedFunctionData == functionData) { // Match! - connection.thisObject.Dispose(); - connection.function.Dispose(); - connection.thisObject.Clear(); - connection.function.Clear(); + qPersistentDispose(connection.thisObject); + qPersistentDispose(connection.function); connections.removeAt(ii); return v8::Undefined(); } @@ -1102,10 +1096,8 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args) connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() && (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) { // Match! - connection.thisObject.Dispose(); - connection.function.Dispose(); - connection.thisObject.Clear(); - connection.function.Clear(); + qPersistentDispose(connection.thisObject); + qPersistentDispose(connection.function); connections.removeAt(ii); return v8::Undefined(); } diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp index 2067f73fae..b4a510e2be 100644 --- a/src/declarative/qml/v8/qv8typewrapper.cpp +++ b/src/declarative/qml/v8/qv8typewrapper.cpp @@ -83,7 +83,7 @@ QV8TypeWrapper::~QV8TypeWrapper() void QV8TypeWrapper::destroy() { - m_constructor.Dispose(); + qPersistentDispose(m_constructor); } void QV8TypeWrapper::init(QV8Engine *engine) @@ -92,7 +92,7 @@ void QV8TypeWrapper::init(QV8Engine *engine) v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode) diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp index 6dfb4312bc..b16a81e607 100644 --- a/src/declarative/qml/v8/qv8valuetypewrapper.cpp +++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp @@ -103,7 +103,7 @@ QV8ValueTypeWrapper::~QV8ValueTypeWrapper() void QV8ValueTypeWrapper::destroy() { - m_constructor.Dispose(); + qPersistentDispose(m_constructor); } void QV8ValueTypeWrapper::init(QV8Engine *engine) @@ -112,7 +112,7 @@ void QV8ValueTypeWrapper::init(QV8Engine *engine) v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(QObject *object, int property, QDeclarativeValueType *type) diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp index de3cb11926..ef1f972ad1 100644 --- a/src/declarative/qml/v8/qv8variantwrapper.cpp +++ b/src/declarative/qml/v8/qv8variantwrapper.cpp @@ -74,11 +74,11 @@ void QV8VariantWrapper::init(QV8Engine *engine) v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } { - m_preserve = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(Preserve)->GetFunction()); - m_destroy = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(Destroy)->GetFunction()); + m_preserve = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Preserve)->GetFunction()); + m_destroy = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Destroy)->GetFunction()); v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); @@ -88,17 +88,17 @@ void QV8VariantWrapper::init(QV8Engine *engine) ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0, m_destroy, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - m_scarceConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + m_scarceConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); } } void QV8VariantWrapper::destroy() { - m_destroy.Dispose(); m_destroy.Clear(); - m_preserve.Dispose(); m_preserve.Clear(); - m_scarceConstructor.Dispose(); m_scarceConstructor.Clear(); - m_constructor.Dispose(); m_constructor.Clear(); + qPersistentDispose(m_destroy); + qPersistentDispose(m_preserve); + qPersistentDispose(m_scarceConstructor); + qPersistentDispose(m_constructor); } v8::Local<v8::Object> QV8VariantWrapper::newVariant(const QVariant &value) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 1f26140909..d4af0b17b2 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -102,12 +102,12 @@ QDeclarativeListModelV8Data::QDeclarativeListModelV8Data() v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); - constructor = v8::Persistent<v8::Function>::New(ft->GetFunction()); + constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } QDeclarativeListModelV8Data::~QDeclarativeListModelV8Data() { - constructor.Dispose(); constructor.Clear(); + qPersistentDispose(constructor); } v8::Handle<v8::Value> QDeclarativeListModelV8Data::Getter(v8::Local<v8::String> property, |