From 2fe8eb61d878c74674415ec32d1d0b420a7c656f Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 15 Jul 2009 10:40:24 +0200 Subject: implement QObject wrapper caching (PreferExistingWrapperObject) --- src/script/api/qscriptengine.cpp | 14 ++++++++++++-- src/script/bridge/qscriptqobject.cpp | 29 +++++++++++++++++++++++++++++ src/script/bridge/qscriptqobject_p.h | 20 +++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 5f63fde..562515d 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -999,9 +999,19 @@ JSC::JSValue QScriptEnginePrivate::newQObject( if (!object) return JSC::jsNull(); JSC::ExecState* exec = currentFrame; - QScriptObject *result = new (exec) QScriptObject(qobjectWrapperObjectStructure); + QScript::QObjectData *data = qobjectData(object); + bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0; + QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject; + QScriptObject *result = 0; + if (preferExisting) + result = data->findWrapper(ownership, opt); + if (!result) { + result = new (exec) QScriptObject(qobjectWrapperObjectStructure); + if (preferExisting) + data->registerWrapper(result, ownership, opt); + } + Q_ASSERT(result != 0); result->setDelegate(new QScript::QObjectDelegate(object, ownership, options)); - // ### TODO /*if (setDefaultPrototype)*/ { const QMetaObject *meta = object->metaObject(); while (meta) { diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 0f54ec9..e668df3 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -1926,6 +1926,17 @@ void QObjectData::mark() { if (connectionManager) connectionManager->mark(); + { + QList::iterator it; + for (it = wrappers.begin(); it != wrappers.end(); ) { + const QScript::QObjectWrapperInfo &info = *it; + if (info.object->marked()) { + ++it; + } else { + it = wrappers.erase(it); + } + } + } } bool QObjectData::addSignalHandler(QObject *sender, @@ -1951,6 +1962,24 @@ bool QObjectData::removeSignalHandler(QObject *sender, sender, signalIndex, receiver, slot); } +QScriptObject *QObjectData::findWrapper(QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) const +{ + for (int i = 0; i < wrappers.size(); ++i) { + const QObjectWrapperInfo &info = wrappers.at(i); + if ((info.ownership == ownership) && (info.options == options)) + return info.object; + } + return 0; +} + +void QObjectData::registerWrapper(QScriptObject *wrapper, + QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) +{ + wrappers.append(QObjectWrapperInfo(wrapper, ownership, options)); +} + } // namespace QScript namespace JSC diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h index 986ea0f..9008599 100644 --- a/src/script/bridge/qscriptqobject_p.h +++ b/src/script/bridge/qscriptqobject_p.h @@ -105,6 +105,18 @@ public: class QObjectConnectionManager; +struct QObjectWrapperInfo +{ + QObjectWrapperInfo(QScriptObject *obj, + QScriptEngine::ValueOwnership own, + const QScriptEngine::QObjectWrapOptions &opt) + : object(obj), ownership(own), options(opt) {} + + QScriptObject *object; + QScriptEngine::ValueOwnership ownership; + QScriptEngine::QObjectWrapOptions options; +}; + class QObjectData // : public QObjectUserData { public: @@ -121,12 +133,18 @@ public: JSC::JSValue receiver, JSC::JSValue slot); + QScriptObject *findWrapper(QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) const; + void registerWrapper(QScriptObject *wrapper, + QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options); + void mark(); private: QScriptEnginePrivate *engine; QScript::QObjectConnectionManager *connectionManager; -// QList wrappers; + QList wrappers; }; class QtFunction: public JSC::InternalFunction -- cgit v0.12