From 28a8c6b02e52bce8b2ac14961997b9c2cc0e01fd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 6 Aug 2009 14:10:50 +1000 Subject: Use meta property cache for property restores --- src/declarative/qml/qmlengine_p.h | 4 ++ src/declarative/qml/qmlmetaproperty.cpp | 103 +++++++++++++++++++++----------- src/declarative/qml/qmlmetaproperty_p.h | 13 +++- 3 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index dffae6c..602321d 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -179,6 +179,10 @@ public: QmlValueTypeFactory valueTypes; QHash propertyCache; + static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) { + if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0; + return &priv->propertyCache[obj->metaObject()]; + } struct Imports { Imports(); diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 350d84b..c445599 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -56,25 +56,53 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE -QmlMetaObjectCache::Data -QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject) +QmlMetaObjectCache::QmlMetaObjectCache() +: propertyCache(0) { - QHash::ConstIterator iter = properties.find(name); - if (iter != properties.end()) { - return *iter; - } else { - Data cacheData = { -1, -1 }; +} + +void QmlMetaObjectCache::init(const QMetaObject *metaObject) +{ + if (propertyCache || !metaObject) + return; + + int propCount = metaObject->propertyCount(); + + propertyCache = new Data[propCount]; + for (int ii = 0; ii < propCount; ++ii) { + QMetaProperty p = metaObject->property(ii); + propertyCache[ii].propType = p.userType(); + propertyCache[ii].coreIndex = ii; + propertyCache[ii].name = QLatin1String(p.name()); + + propertyNameCache.insert(propertyCache[ii].name, ii); + } +} + +QmlMetaObjectCache::~QmlMetaObjectCache() +{ + delete [] propertyCache; +} + +QmlMetaObjectCache::Data * +QmlMetaObjectCache::property(int index, const QMetaObject *metaObject) +{ + init(metaObject); - int idx = metaObject->indexOfProperty(name.toUtf8().constData()); - if (idx == -1) - return cacheData; + return propertyCache + index; +} + +QmlMetaObjectCache::Data * +QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject) +{ + init(metaObject); - QMetaProperty property = metaObject->property(idx); - cacheData.propType = property.userType(); - cacheData.coreIndex = idx; - properties.insert(name, cacheData); + QHash::ConstIterator iter = propertyNameCache.find(name); - return cacheData; + if (iter != propertyNameCache.end()) { + return propertyCache + *iter; + } else { + return 0; } } @@ -99,14 +127,6 @@ QmlMetaProperty::~QmlMetaProperty() delete d; d = 0; } -struct CachedPropertyData { - CachedPropertyData(const QString &n, int pt, int ci) - : name(n), propType(pt), coreIdx(ci) {} - QString name; - int propType; - int coreIdx; -}; - /*! Creates a QmlMetaProperty for the default property of \a obj. If there is no default property, an invalid QmlMetaProperty will be created. @@ -218,15 +238,14 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) } // Property - if (!QObjectPrivate::get(obj)->metaObject && enginePrivate) { - // Can cache - QmlMetaObjectCache &cache = - enginePrivate->propertyCache[obj->metaObject()]; - QmlMetaObjectCache::Data data = cache.property(name, obj->metaObject()); - if (data.coreIndex != -1) { + QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj); + if (cache) { + QmlMetaObjectCache::Data *data = + cache->property(name, obj->metaObject()); + if (data) { type = QmlMetaProperty::Property; - propType = data.propType; - coreIdx = data.coreIndex; + propType = data->propType; + coreIdx = data->coreIndex; } } else { // Can't cache @@ -1015,6 +1034,10 @@ quint32 QmlMetaPropertyPrivate::saveProperty(int core) */ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) { + QmlEnginePrivate *enginePrivate = 0; + if (ctxt && ctxt->engine()) + enginePrivate = QmlEnginePrivate::get(ctxt->engine()); + d->object = obj; d->context = ctxt; @@ -1042,10 +1065,22 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) d->valueTypeId = p.type(); } else if (d->type & Property) { - QMetaProperty p(obj->metaObject()->property(id)); - d->name = QLatin1String(p.name()); - d->propType = p.userType(); + + QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj); + d->coreIdx = id; + + if (cache) { + QmlMetaObjectCache::Data *data = + cache->property(id, obj->metaObject()); + d->propType = data->propType; + d->name = data->name; + } else { + QMetaProperty p(obj->metaObject()->property(id)); + d->name = QLatin1String(p.name()); + d->propType = p.userType(); + } + } else if (d->type & SignalProperty) { d->signal = obj->metaObject()->method(id); d->coreIdx = id; diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 0410dd6..8e8966e 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -61,14 +61,23 @@ QT_BEGIN_NAMESPACE class QmlMetaObjectCache { public: + QmlMetaObjectCache(); + ~QmlMetaObjectCache(); + struct Data { int propType; int coreIndex; + QString name; }; - QHash properties; + Data *property(const QString &, const QMetaObject *); + Data *property(int, const QMetaObject *); + +private: + void init(const QMetaObject *); - Data property(const QString &, const QMetaObject *); + Data *propertyCache; + QHash propertyNameCache; }; class QmlContext; -- cgit v0.12 From 3270c41c1e1f78b403a4d587d726203520eb707b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 6 Aug 2009 15:50:49 +1000 Subject: Add a QmlMetaType::typeCategory() method QmlMetaProperty was calling isObject(), isList() and isQmlList() to determine its property category, resulting in acquiring and releasing three locks (one for each call). This call allows QmlMetaProperty to do the same with only one lock. --- src/declarative/qml/qmlmetaproperty.cpp | 25 +++++++++++++++++-------- src/declarative/qml/qmlmetatype.cpp | 16 ++++++++++++++++ src/declarative/qml/qmlmetatype.h | 3 +++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index c445599..09ca872 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -310,14 +310,23 @@ QmlMetaPropertyPrivate::propertyCategory() const category = QmlMetaProperty::Normal; else if (type == qMetaTypeId()) category = QmlMetaProperty::Bindable; - else if (QmlMetaType::isList(type)) - category = QmlMetaProperty::List; - else if (QmlMetaType::isQmlList(type)) - category = QmlMetaProperty::QmlList; - else if (QmlMetaType::isObject(type)) - category = QmlMetaProperty::Object; - else - category = QmlMetaProperty::Normal; + else { + QmlMetaType::TypeCategory tc = QmlMetaType::typeCategory(type); + switch(tc) { + case QmlMetaType::Object: + category = QmlMetaProperty::Object; + break; + case QmlMetaType::QmlList: + category = QmlMetaProperty::QmlList; + break; + case QmlMetaType::List: + category = QmlMetaProperty::List; + break; + case QmlMetaType::Unknown: + category = QmlMetaProperty::Normal; + break; + } + } } return category; } diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 29fe026..50bc676 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -794,6 +794,22 @@ QMetaProperty QmlMetaType::property(QObject *obj, const char *name) return metaObject->property(idx); } +QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType) +{ + if (userType < 0) + return Unknown; + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + if (userType < data->objects.size() && data->objects.testBit(userType)) + return Object; + else if (userType < data->qmllists.size() && data->qmllists.testBit(userType)) + return QmlList; + else if (userType < data->lists.size() && data->lists.testBit(userType)) + return List; + else + return Unknown; +} + bool QmlMetaType::isObject(int userType) { QReadLocker lock(metaTypeDataLock()); diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index e023e83..9cbf7f3 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -94,6 +94,9 @@ public: static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int); static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &); + enum TypeCategory { Unknown, Object, List, QmlList }; + static TypeCategory typeCategory(int); + static bool isInterface(int); static const char *interfaceIId(int); static bool isObject(int); -- cgit v0.12