aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2014-11-20 09:07:52 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2014-12-29 14:39:22 +0100
commitefc3cc717ac1a62965465e909cc99acef627cdb1 (patch)
tree9d181ca8e9e299fa99b9b7598bfb83bc53056dde /src/qml
parent65953304a2775e69c7edd46b780aa39f769d32ac (diff)
Make QQmlPropertyCache available in QJSEngine
The QQmlEngine has two containers for property caches, one for QML types and one for all-purpose meta-objects. The latter is rather useful and now being moved to QJSEngine to be available there. Change-Id: Ieab65c400b8a2e410e5f9eee6d603162dbb864d9 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsapi/qjsengine.cpp21
-rw-r--r--src/qml/jsapi/qjsengine_p.h125
-rw-r--r--src/qml/jsruntime/qv4script.cpp2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp2
-rw-r--r--src/qml/qml/qqmlengine.cpp20
-rw-r--r--src/qml/qml/qqmlengine_p.h108
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp1
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp13
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h10
9 files changed, 161 insertions, 141 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index e4daa64674..04ed341a50 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -539,6 +539,27 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
\sa toScriptValue()
*/
+
+QJSEnginePrivate::~QJSEnginePrivate()
+{
+ for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
+ (*iter)->release();
+}
+
+QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo)
+{
+ if (!mo->superClass()) {
+ QQmlPropertyCache *rv = new QQmlPropertyCache(q_func(), mo);
+ propertyCache.insert(mo, rv);
+ return rv;
+ } else {
+ QQmlPropertyCache *super = cache(mo->superClass());
+ QQmlPropertyCache *rv = super->copyAndAppend(mo);
+ propertyCache.insert(mo, rv);
+ return rv;
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qjsengine.cpp"
diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h
index 654d0dee56..eba8ffb4be 100644
--- a/src/qml/jsapi/qjsengine_p.h
+++ b/src/qml/jsapi/qjsengine_p.h
@@ -46,11 +46,13 @@
//
#include <QtCore/private/qobject_p.h>
+#include <QtCore/qmutex.h>
#include "qjsengine.h"
QT_BEGIN_NAMESPACE
+class QQmlPropertyCache;
class QJSEnginePrivate : public QObjectPrivate
{
@@ -58,10 +60,131 @@ class QJSEnginePrivate : public QObjectPrivate
public:
static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); }
+ static const QJSEnginePrivate* get(const QJSEngine*e) { return e->d_func(); }
- QJSEnginePrivate() {}
+ QJSEnginePrivate() : mutex(QMutex::Recursive) {}
+ ~QJSEnginePrivate();
+
+ // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
+ // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
+ // either idle, or is running with the main thread blocked, no locking is necessary. This way
+ // we only pay for locking when we have to.
+ // Consequently, this class should only be used to protect simple accesses or modifications of the
+ // QQmlEnginePrivate structures or operations that can be guaranteed not to start activity
+ // on the loader thread.
+ // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
+ // QMutex instance and multiple Lockers are recursive in the same thread.
+ class Locker
+ {
+ public:
+ inline Locker(const QJSEngine *);
+ inline Locker(const QJSEnginePrivate *);
+ inline ~Locker();
+
+ inline void unlock();
+ inline void relock();
+
+ private:
+ const QJSEnginePrivate *m_ep;
+ quint32 m_locked:1;
+ };
+
+ // Shared by QQmlEngine
+ mutable QMutex mutex;
+
+
+ // These methods may be called from the QML loader thread
+ inline QQmlPropertyCache *cache(QObject *obj);
+ inline QQmlPropertyCache *cache(const QMetaObject *);
+
+private:
+ // Must be called locked
+ QQmlPropertyCache *createCache(const QMetaObject *);
+
+ // These members must be protected by a QJSEnginePrivate::Locker as they are required by
+ // the threaded loader. Only access them through their respective accessor methods.
+ QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
};
+QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
+: m_ep(QJSEnginePrivate::get(e))
+{
+ relock();
+}
+
+QJSEnginePrivate::Locker::Locker(const QJSEnginePrivate *e)
+: m_ep(e), m_locked(false)
+{
+ relock();
+}
+
+QJSEnginePrivate::Locker::~Locker()
+{
+ unlock();
+}
+
+void QJSEnginePrivate::Locker::unlock()
+{
+ if (m_locked) {
+ m_ep->mutex.unlock();
+ m_locked = false;
+ }
+}
+
+void QJSEnginePrivate::Locker::relock()
+{
+ Q_ASSERT(!m_locked);
+ m_ep->mutex.lock();
+ m_locked = true;
+}
+
+/*!
+Returns a QQmlPropertyCache for \a obj if one is available.
+
+If \a obj is null, being deleted or contains a dynamic meta object 0
+is returned.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+
+XXX thread There is a potential future race condition in this and all the cache()
+functions. As the QQmlPropertyCache is returned unreferenced, when called
+from the loader thread, it is possible that the cache will have been dereferenced
+and deleted before the loader thread has a chance to use or reference it. This
+can't currently happen as the cache holds a reference to the
+QQmlPropertyCache until the QQmlEngine is destroyed.
+*/
+QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj)
+{
+ if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
+ return 0;
+
+ Locker locker(this);
+ const QMetaObject *mo = obj->metaObject();
+ QQmlPropertyCache *rv = propertyCache.value(mo);
+ if (!rv) rv = createCache(mo);
+ return rv;
+}
+
+/*!
+Returns a QQmlPropertyCache for \a metaObject.
+
+As the cache is persisted for the life of the engine, \a metaObject must be
+a static "compile time" meta-object, or a meta-object that is otherwise known to
+exist for the lifetime of the QQmlEngine.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+*/
+QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject)
+{
+ Q_ASSERT(metaObject);
+
+ Locker locker(this);
+ QQmlPropertyCache *rv = propertyCache.value(metaObject);
+ if (!rv) rv = createCache(metaObject);
+ return rv;
+}
+
+
QT_END_NAMESPACE
#endif // QJSENGINE_P_H
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 088e9616ce..38d2c12cfb 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -176,7 +176,7 @@ Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContex
if (!signalParameters.isEmpty()) {
if (error)
- QQmlPropertyCache::signalParameterStringForJS(qmlContext->engine, signalParameters, error);
+ QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
QV4::ScopedProperty p(valueScope);
QV4::ScopedString s(valueScope);
int index = 0;
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index f8718ad0ee..8baeefe62b 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -217,7 +217,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
//TODO: look at using the property cache here (as in the compiler)
// for further optimization
QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
- expression += QQmlPropertyCache::signalParameterStringForJS(engine(), signal.parameterNames(), &error);
+ expression += QQmlPropertyCache::signalParameterStringForJS(scope.engine, signal.parameterNames(), &error);
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index f9de7adc93..8f2c554a7e 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -559,7 +559,7 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
activeObjectCreator(0),
networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0),
scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
- incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
+ incubatorCount(0), incubationController(0)
{
}
@@ -582,8 +582,6 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
if (incubationController) incubationController->d = 0;
incubationController = 0;
- for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
- (*iter)->release();
for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
(*iter)->release();
for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
@@ -2043,22 +2041,6 @@ QString QQmlEngine::offlineStoragePath() const
return d->offlineStoragePath;
}
-QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
-{
- Q_Q(QQmlEngine);
-
- if (!mo->superClass()) {
- QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
- propertyCache.insert(mo, rv);
- return rv;
- } else {
- QQmlPropertyCache *super = cache(mo->superClass());
- QQmlPropertyCache *rv = super->copyAndAppend(mo);
- propertyCache.insert(mo, rv);
- return rv;
- }
-}
-
QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
QQmlError &error)
{
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index a1935b854b..de2a2d3e1d 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -208,9 +208,8 @@ public:
inline static void deleteInEngineThread(QQmlEngine *, T *);
// These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(QObject *obj);
- inline QQmlPropertyCache *cache(const QMetaObject *);
inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
+ using QJSEnginePrivate::cache;
// These methods may be called from the loader thread
bool isQObject(int);
@@ -260,40 +259,13 @@ public:
static bool qml_debugging_enabled;
mutable QMutex networkAccessManagerMutex;
- mutable QMutex mutex;
private:
- // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
- // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
- // either idle, or is running with the main thread blocked, no locking is necessary. This way
- // we only pay for locking when we have to.
- // Consequently, this class should only be used to protect simple accesses or modifications of the
- // QQmlEnginePrivate structures or operations that can be guaranteed not to start activity
- // on the loader thread.
- // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
- // QMutex instance and multiple Lockers are recursive in the same thread.
- class Locker
- {
- public:
- inline Locker(const QQmlEngine *);
- inline Locker(const QQmlEnginePrivate *);
- inline ~Locker();
-
- inline void unlock();
- inline void relock();
-
- private:
- const QQmlEnginePrivate *m_ep;
- quint32 m_locked:1;
- };
-
// Must be called locked
- QQmlPropertyCache *createCache(const QMetaObject *);
QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
- QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
QHash<int, int> m_qmlLists;
QHash<int, QQmlCompiledData *> m_compositeTypes;
@@ -306,38 +278,6 @@ private:
void doDeleteInEngineThread();
};
-QQmlEnginePrivate::Locker::Locker(const QQmlEngine *e)
-: m_ep(QQmlEnginePrivate::get(e))
-{
- relock();
-}
-
-QQmlEnginePrivate::Locker::Locker(const QQmlEnginePrivate *e)
-: m_ep(e), m_locked(false)
-{
- relock();
-}
-
-QQmlEnginePrivate::Locker::~Locker()
-{
- unlock();
-}
-
-void QQmlEnginePrivate::Locker::unlock()
-{
- if (m_locked) {
- m_ep->mutex.unlock();
- m_locked = false;
- }
-}
-
-void QQmlEnginePrivate::Locker::relock()
-{
- Q_ASSERT(!m_locked);
- m_ep->mutex.lock();
- m_locked = true;
-}
-
/*!
Returns true if the calling thread is the QQmlEngine thread.
*/
@@ -402,52 +342,6 @@ void QQmlEnginePrivate::deleteInEngineThread(QQmlEngine *engine, T *value)
}
/*!
-Returns a QQmlPropertyCache for \a obj if one is available.
-
-If \a obj is null, being deleted or contains a dynamic meta object 0
-is returned.
-
-The returned cache is not referenced, so if it is to be stored, call addref().
-
-XXX thread There is a potential future race condition in this and all the cache()
-functions. As the QQmlPropertyCache is returned unreferenced, when called
-from the loader thread, it is possible that the cache will have been dereferenced
-and deleted before the loader thread has a chance to use or reference it. This
-can't currently happen as the cache holds a reference to the
-QQmlPropertyCache until the QQmlEngine is destroyed.
-*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(QObject *obj)
-{
- if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
- return 0;
-
- Locker locker(this);
- const QMetaObject *mo = obj->metaObject();
- QQmlPropertyCache *rv = propertyCache.value(mo);
- if (!rv) rv = createCache(mo);
- return rv;
-}
-
-/*!
-Returns a QQmlPropertyCache for \a metaObject.
-
-As the cache is persisted for the life of the engine, \a metaObject must be
-a static "compile time" meta-object, or a meta-object that is otherwise known to
-exist for the lifetime of the QQmlEngine.
-
-The returned cache is not referenced, so if it is to be stored, call addref().
-*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(const QMetaObject *metaObject)
-{
- Q_ASSERT(metaObject);
-
- Locker locker(this);
- QQmlPropertyCache *rv = propertyCache.value(metaObject);
- if (!rv) rv = createCache(metaObject);
- return rv;
-}
-
-/*!
Returns a QQmlPropertyCache for \a type with \a minorVersion.
The returned cache is not referenced, so if it is to be stored, call addref().
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 9715fdc85d..e234a0bfbe 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <qqmlengine.h>
#include <qdebug.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 363fce4375..b5bc29aaa6 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -231,7 +231,7 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
/*!
Creates a new empty QQmlPropertyCache.
*/
-QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
+QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
_metaObject(0), argumentsCache(0)
@@ -242,7 +242,7 @@ QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e, const QMetaObject *metaObject)
+QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e, const QMetaObject *metaObject)
: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
_metaObject(0), argumentsCache(0)
@@ -818,7 +818,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
}
}
- data->flags |= flagsForPropertyType(data->propType, engine);
+ data->flags |= flagsForPropertyType(data->propType, qobject_cast<QQmlEngine*>(engine));
}
data->flags &= ~QQmlPropertyData::NotFullyResolved;
@@ -1135,7 +1135,7 @@ QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorS
}
QString error;
- QString parameters = signalParameterStringForJS(engine, parameterNameList, &error);
+ QString parameters = signalParameterStringForJS(QV8Engine::getV4(engine), parameterNameList, &error);
A *arguments = static_cast<A *>(signalData->arguments);
arguments->signalParameterStringForJS = new QString(!error.isEmpty() ? error : parameters);
@@ -1148,11 +1148,10 @@ QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorS
return *arguments->signalParameterStringForJS;
}
-QString QQmlPropertyCache::signalParameterStringForJS(QQmlEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
+QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
{
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
bool unnamedParameter = false;
- const QSet<QString> &illegalNames = ep->v8engine()->illegalNames();
+ const QSet<QString> &illegalNames = engine->v8Engine->illegalNames();
QString error;
QString parameters;
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index d3ea336885..224de948eb 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
class QV8Engine;
class QMetaProperty;
class QQmlEngine;
+class QJSEngine;
class QQmlPropertyData;
class QQmlAccessors;
class QMetaObjectBuilder;
@@ -242,8 +243,8 @@ class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
public:
- QQmlPropertyCache(QQmlEngine *);
- QQmlPropertyCache(QQmlEngine *, const QMetaObject *);
+ QQmlPropertyCache(QJSEngine *);
+ QQmlPropertyCache(QJSEngine *, const QMetaObject *);
virtual ~QQmlPropertyCache();
void update(const QMetaObject *);
@@ -311,7 +312,7 @@ public:
QList<QByteArray> signalParameterNames(int index) const;
QString signalParameterStringForJS(int index, QString *errorString = 0);
- static QString signalParameterStringForJS(QQmlEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString = 0);
+ static QString signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString = 0);
const char *className() const;
@@ -374,8 +375,7 @@ private:
_hasPropertyOverrides |= isOverride;
}
- // Optional! Only used for calling flagsForPropertyType, in which it is also optional.
- QQmlEngine *engine;
+ QJSEngine *engine;
QQmlPropertyCache *_parent;
int propertyIndexCacheStart;