diff options
15 files changed, 200 insertions, 85 deletions
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 321feb9..c331f56 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -196,7 +196,7 @@ QmlEnginePrivate::queryObject(const QString &propName, { QScriptClass::QueryFlags rv = 0; - QmlMetaProperty prop(obj, propName); + QmlMetaProperty prop(obj, propName, rootContext); if (prop.type() == QmlMetaProperty::Invalid) { QPair<const QMetaObject *, QString> key = qMakePair(obj->metaObject(), propName); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 18cdd83..dffae6c 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -71,6 +71,7 @@ #include <QtDeclarative/qmlengine.h> #include <QtDeclarative/qmlexpression.h> #include <QtScript/qscriptengine.h> +#include <private/qmlmetaproperty_p.h> QT_BEGIN_NAMESPACE @@ -177,6 +178,7 @@ public: } QmlValueTypeFactory valueTypes; + QHash<const QMetaObject *, QmlMetaObjectCache> propertyCache; struct Imports { Imports(); diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 3d040e5..e6ffd50 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -56,31 +56,27 @@ Q_DECLARE_METATYPE(QList<QObject *>); QT_BEGIN_NAMESPACE -class QMetaPropertyEx : public QMetaProperty +QmlMetaObjectCache::Data +QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject) { -public: - QMetaPropertyEx() - : propertyType(-1) {} - - QMetaPropertyEx(const QMetaProperty &p) - : QMetaProperty(p), propertyType(p.userType()) {} - - QMetaPropertyEx(const QMetaPropertyEx &o) - : QMetaProperty(o), - propertyType(o.propertyType) {} - - QMetaPropertyEx &operator=(const QMetaPropertyEx &o) - { - static_cast<QMetaProperty *>(this)->operator=(o); - propertyType = o.propertyType; - return *this; - } + QHash<QString, Data>::ConstIterator iter = properties.find(name); + if (iter != properties.end()) { + return *iter; + } else { + Data cacheData = { -1, -1 }; - private: - friend class QmlMetaProperty; - int propertyType; -}; + int idx = metaObject->indexOfProperty(name.toUtf8().constData()); + if (idx == -1) + return cacheData; + QMetaProperty property = metaObject->property(idx); + cacheData.propType = property.userType(); + cacheData.coreIndex = idx; + properties.insert(name, cacheData); + + return cacheData; + } +} /*! \class QmlMetaProperty @@ -111,16 +107,13 @@ struct CachedPropertyData { int coreIdx; }; -// ### not thread safe -static QHash<const QMetaObject *, CachedPropertyData> qmlCacheDefProp; - /*! Creates a QmlMetaProperty for the default property of \a obj. If there is no default property, an invalid QmlMetaProperty will be created. */ QmlMetaProperty::QmlMetaProperty(QObject *obj) { - initDefault(obj); + d->initDefault(obj); } /*! @@ -132,32 +125,24 @@ QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt) : d(new QmlMetaPropertyPrivate) { d->context = ctxt; - initDefault(obj); + d->initDefault(obj); } -void QmlMetaProperty::initDefault(QObject *obj) +/*! + Initialize from the default property of \a obj +*/ +void QmlMetaPropertyPrivate::initDefault(QObject *obj) { if (!obj) return; - d->object = obj; - QHash<const QMetaObject *, CachedPropertyData>::ConstIterator iter = - qmlCacheDefProp.find(obj->metaObject()); - if (iter != qmlCacheDefProp.end()) { - d->name = iter->name; - d->propType = iter->propType; - d->coreIdx = iter->coreIdx; - } else { - QMetaPropertyEx p(QmlMetaType::defaultProperty(obj)); - d->name = QLatin1String(p.name()); - d->propType = p.propertyType; - d->coreIdx = p.propertyIndex(); - if (!QObjectPrivate::get(obj)->metaObject) - qmlCacheDefProp.insert(obj->metaObject(), CachedPropertyData(d->name, d->propType, d->coreIdx)); - } - if (!d->name.isEmpty()) { - d->type = Property | Default; - } + object = obj; + QMetaProperty p = QmlMetaType::defaultProperty(obj); + name = QLatin1String(p.name()); + propType = p.userType();; + coreIdx = p.propertyIndex(); + if (!name.isEmpty()) + type = QmlMetaProperty::Property | QmlMetaProperty::Default; } /*! @@ -171,22 +156,20 @@ QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, QmlContext *ctxt) d->context = ctxt; d->object = obj; d->type = Property; - QMetaPropertyEx p(obj->metaObject()->property(idx)); - d->propType = p.propertyType; + QMetaProperty p = obj->metaObject()->property(idx); + d->propType = p.userType(); d->coreIdx = idx; if (p.name() != 0) d->name = QLatin1String(p.name()); } -// ### Not thread safe!!!! -static QHash<const QMetaObject *, QHash<QString, CachedPropertyData> > qmlCacheProps; /*! Creates a QmlMetaProperty for the property \a name of \a obj. */ QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name) : d(new QmlMetaPropertyPrivate) { - initProperty(obj, name); + d->initProperty(obj, name); } /*! @@ -197,51 +180,62 @@ QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext * : d(new QmlMetaPropertyPrivate) { d->context = ctxt; - initProperty(obj, name); + d->initProperty(obj, name); } -void QmlMetaProperty::initProperty(QObject *obj, const QString &name) +void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) { - d->name = name; - d->object = obj; + QmlEnginePrivate *enginePrivate = 0; + if (context && context->engine()) + enginePrivate = QmlEnginePrivate::get(context->engine()); + + this->name = name; + object = obj; + if (name.isEmpty() || !obj) return; if (name.at(0).isUpper()) { // Attached property - d->attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1()); - if (d->attachedFunc != -1) - d->type = Property | Attached; + attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1()); + if (attachedFunc != -1) + type = QmlMetaProperty::Property | QmlMetaProperty::Attached; return; - } else if (name.count() >= 3 && name.startsWith(QLatin1String("on")) && name.at(2).isUpper()) { + + } else if (name.count() >= 3 && + name.at(0) == QChar(QLatin1Char('o')) && + name.at(1) == QChar(QLatin1Char('n')) && + name.at(2).isUpper()) { // Signal QString signalName = name.mid(2); signalName[0] = signalName.at(0).toLower(); - d->findSignalInt(obj, signalName); - if (d->signal.signature() != 0) { - d->type = SignalProperty; + findSignalInt(obj, signalName); + if (signal.signature() != 0) { + type = QmlMetaProperty::SignalProperty; return; } } // Property - QHash<QString, CachedPropertyData> &props = qmlCacheProps[obj->metaObject()]; - QHash<QString, CachedPropertyData>::ConstIterator iter = props.find(name); - if (iter != props.end()) { - d->name = iter->name; - d->propType = iter->propType; - d->coreIdx = iter->coreIdx; + 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) { + type = QmlMetaProperty::Property; + propType = data.propType; + coreIdx = data.coreIndex; + } } else { - QMetaPropertyEx p = QmlMetaType::property(obj, name.toLatin1().constData()); - d->name = QLatin1String(p.name()); - d->propType = p.propertyType; - d->coreIdx = p.propertyIndex(); - if (!QObjectPrivate::get(obj)->metaObject) - props.insert(name, CachedPropertyData(d->name, d->propType, d->coreIdx)); + // Can't cache + QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData()); + propType = p.userType(); + coreIdx = p.propertyIndex(); + if (p.name()) + type = QmlMetaProperty::Property; } - if (!d->name.isEmpty()) - d->type = Property; } /*! @@ -1037,18 +1031,18 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) QmlValueType *valueType = qmlValueTypes()->valueTypes[p.type()]; - QMetaPropertyEx p2(valueType->metaObject()->property(valueTypeIdx)); + QMetaProperty p2(valueType->metaObject()->property(valueTypeIdx)); d->name = QLatin1String(p2.name()); - d->propType = p2.propertyType; + d->propType = p2.userType(); d->coreIdx = coreIdx; d->valueTypeIdx = valueTypeIdx; d->valueTypeId = p.type(); } else if (d->type & Property) { - QMetaPropertyEx p(obj->metaObject()->property(id)); + QMetaProperty p(obj->metaObject()->property(id)); d->name = QLatin1String(p.name()); - d->propType = p.propertyType; + d->propType = p.userType(); d->coreIdx = id; } else if (d->type & SignalProperty) { d->signal = obj->metaObject()->method(id); @@ -1086,7 +1080,7 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj, QmlMetaProperty prop(object, pathName); if (jj == path.count() - 2 && - prop.propertyType() < QVariant::UserType && + prop.propertyType() < (int)QVariant::UserType && qmlValueTypes()->valueTypes[prop.propertyType()]) { // We're now at a value type property QObject *typeObject = diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 2470d5d..434ff55 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -129,8 +129,6 @@ public: int coreIndex() const; private: - void initDefault(QObject *obj); - void initProperty(QObject *obj, const QString &name); friend class QmlEnginePrivate; QmlMetaPropertyPrivate *d; }; diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 64cdbae..0410dd6 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -58,6 +58,19 @@ QT_BEGIN_NAMESPACE +class QmlMetaObjectCache +{ +public: + struct Data { + int propType; + int coreIndex; + }; + + QHash<QString, Data> properties; + + Data property(const QString &, const QMetaObject *); +}; + class QmlContext; class QmlMetaPropertyPrivate { @@ -86,6 +99,9 @@ public: mutable QmlMetaProperty::PropertyCategory category; + void initProperty(QObject *obj, const QString &name); + void initDefault(QObject *obj); + QObject *attachedObject() const; void findSignalInt(QObject *, const QString &); diff --git a/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt b/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt index 05ed87a..9c3f7f8 100644 --- a/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt +++ b/tests/benchmarks/declarative/qmlcomponent/myqmlobject.txt @@ -1 +1,3 @@ +import Qt.test 4.6 + MyQmlObject {} diff --git a/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt b/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt index 4dfa7c3..e6cc4cf 100644 --- a/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt +++ b/tests/benchmarks/declarative/qmlcomponent/myqmlobject_binding.txt @@ -1,3 +1,5 @@ +import Qt.test 4.6 + MyQmlObject { result: value } diff --git a/tests/benchmarks/declarative/qmlcomponent/object.txt b/tests/benchmarks/declarative/qmlcomponent/object.txt index 7dc75192..85e74b9 100644 --- a/tests/benchmarks/declarative/qmlcomponent/object.txt +++ b/tests/benchmarks/declarative/qmlcomponent/object.txt @@ -1 +1,3 @@ +import Qt 4.6 + Object {} diff --git a/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt index d59104d..90db37c 100644 --- a/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt +++ b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.2.txt @@ -1,3 +1,5 @@ +import Qt 4.6 + Object { property int a property bool b diff --git a/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt index d9eb708..bb5469a 100644 --- a/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt +++ b/tests/benchmarks/declarative/qmlcomponent/synthesized_properties.txt @@ -1,3 +1,5 @@ +import Qt 4.6 + Object { property int a } diff --git a/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp b/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp index 60e69e2..5021bf3 100644 --- a/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp +++ b/tests/benchmarks/declarative/qmlcomponent/testtypes.cpp @@ -1,3 +1,3 @@ #include "testtypes.h" -QML_DEFINE_TYPE(MyQmlObject, MyQmlObject); +QML_DEFINE_TYPE(Qt/test, 4, 6, 6, MyQmlObject, MyQmlObject); diff --git a/tests/benchmarks/declarative/qmlmetaproperty/object.txt b/tests/benchmarks/declarative/qmlmetaproperty/object.txt new file mode 100644 index 0000000..11b95e1 --- /dev/null +++ b/tests/benchmarks/declarative/qmlmetaproperty/object.txt @@ -0,0 +1,3 @@ +import Qt 4.6 + +Item {} diff --git a/tests/benchmarks/declarative/qmlmetaproperty/qmlmetaproperty.pro b/tests/benchmarks/declarative/qmlmetaproperty/qmlmetaproperty.pro new file mode 100644 index 0000000..b4e83d7 --- /dev/null +++ b/tests/benchmarks/declarative/qmlmetaproperty/qmlmetaproperty.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qmlmetaproperty +QT += declarative + +SOURCES += tst_qmlmetaproperty.cpp + diff --git a/tests/benchmarks/declarative/qmlmetaproperty/synthesized_object.txt b/tests/benchmarks/declarative/qmlmetaproperty/synthesized_object.txt new file mode 100644 index 0000000..a923a0a --- /dev/null +++ b/tests/benchmarks/declarative/qmlmetaproperty/synthesized_object.txt @@ -0,0 +1,6 @@ +import Qt 4.6 + +Item { + property int blah +} + diff --git a/tests/benchmarks/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp b/tests/benchmarks/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp new file mode 100644 index 0000000..c22af03 --- /dev/null +++ b/tests/benchmarks/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +****************************************************************************/ + +#include <qtest.h> +#include <QmlEngine> +#include <QmlComponent> +#include <QmlMetaProperty> +#include <QFile> +#include <QDebug> + +//TESTED_FILES= + + +class tst_qmlmetaproperty : public QObject +{ + Q_OBJECT + +public: + tst_qmlmetaproperty(); + virtual ~tst_qmlmetaproperty(); + +public slots: + void init(); + void cleanup(); + +private slots: + void lookup_data(); + void lookup(); + +private: + QmlEngine engine; +}; + +tst_qmlmetaproperty::tst_qmlmetaproperty() +{ +} + +tst_qmlmetaproperty::~tst_qmlmetaproperty() +{ +} + +void tst_qmlmetaproperty::init() +{ +} + +void tst_qmlmetaproperty::cleanup() +{ +} + +void tst_qmlmetaproperty::lookup_data() +{ + QTest::addColumn<QString>("file"); + + QTest::newRow("Simple Object") << "object.txt"; + QTest::newRow("Synthesized Object") << "synthesized_object.txt"; +} + +void tst_qmlmetaproperty::lookup() +{ + QFETCH(QString, file); + + QmlComponent c(&engine, file); + QVERIFY(c.isReady()); + + QObject *obj = c.create(); + + QBENCHMARK { + QmlMetaProperty p(obj, "x"); + } + + delete obj; +} + +QTEST_MAIN(tst_qmlmetaproperty) +#include "tst_qmlmetaproperty.moc" |