From 9e239d0f653e8f37d0befb27aa3165d4723279a0 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 18 May 2012 10:54:09 +1000 Subject: [PATCH] Optimize QML type registration. Change-Id: I981f5e2e6d7f6089e9f326d41a65e54668b73120 Reviewed-by: Michael Brasser --- src/qml/qml/qqml.h | 90 ++++++++++------------ src/qml/qml/qqmlmetatype.cpp | 33 +++++++-- src/qml/qml/qqmlvaluetype_p.h | 2 +- tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp | 2 + 4 files changed, 70 insertions(+), 57 deletions(-) diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index b7f5cb7..9c01ee4 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -89,19 +89,30 @@ QT_BEGIN_NAMESPACE class QQmlPropertyValueInterceptor; +#define QML_GETTYPENAMES \ + const char *className = T::staticMetaObject.className(); \ + int nameLen = strlen(className); \ + QVarLengthArray pointerName(nameLen+2); \ + memcpy(pointerName.data(), className, nameLen); \ + pointerName[nameLen] = '*'; \ + pointerName[nameLen+1] = '\0'; \ + int listLen = strlen("QQmlListProperty<"); \ + QVarLengthArray listName(listLen + nameLen + 2); \ + memcpy(listName.data(), "QQmlListProperty<", listLen); \ + memcpy(listName.data()+listLen, className, nameLen); \ + listName[listLen+nameLen] = '>'; \ + listName[listLen+nameLen+1] = '\0'; + template int qmlRegisterType() { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), 0, 0, QString(), @@ -128,16 +139,13 @@ int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, template int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), 0, 0, reason, @@ -162,16 +170,13 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin template int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), sizeof(T), QQmlPrivate::createInto, QString(), @@ -196,16 +201,13 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c template int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 1, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), sizeof(T), QQmlPrivate::createInto, QString(), @@ -230,16 +232,13 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c template int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 1, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), sizeof(T), QQmlPrivate::createInto, QString(), @@ -265,16 +264,13 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) template int qmlRegisterExtendedType() { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), 0, 0, QString(), @@ -300,10 +296,7 @@ template int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc(); const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject(); @@ -315,8 +308,8 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), sizeof(T), QQmlPrivate::createInto, QString(), @@ -349,8 +342,8 @@ int qmlRegisterInterface(const char *typeName) QQmlPrivate::RegisterInterface qmlInterface = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), qobject_interface_iid() }; @@ -362,16 +355,13 @@ template int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, QQmlCustomParser *parser) { - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QQmlListProperty<" + name + '>'); + QML_GETTYPENAMES QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), - qRegisterMetaType >(listName.constData()), + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), sizeof(T), QQmlPrivate::createInto, QString(), diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 1566d83..87c39b1 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -190,6 +190,25 @@ public: static QHash m_attachedPropertyIds; }; +// Avoid multiple fromUtf8(), copies and hashing of the module name. +// This is only called when metaTypeDataLock is locked. +static QHashedString moduletoUtf8(const char *module) +{ + if (!module) + return QHashedString(); + + static const char *lastModule = 0; + static QHashedString lastModuleStr; + + if (lastModule != module) { + lastModuleStr = QString::fromUtf8(module); + lastModuleStr.hash(); + lastModule = module; + } + + return lastModuleStr; +} + QHash QQmlTypePrivate::m_attachedPropertyIds; QQmlTypePrivate::QQmlTypePrivate() @@ -219,14 +238,9 @@ QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface) QQmlType::QQmlType(int index, const QQmlPrivate::RegisterType &type) : d(new QQmlTypePrivate) { - d->m_module = QString::fromUtf8(type.uri); + d->m_module = moduletoUtf8(type.uri); d->m_elementName = QString::fromUtf8(type.elementName); - if (!d->m_module.isEmpty()) - d->m_name = static_cast(d->m_module) + QLatin1Char('/') + d->m_elementName; - else - d->m_name = d->m_elementName; - d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; if (type.version >= 1) // revisions added in version 1 @@ -498,6 +512,13 @@ const QString &QQmlType::elementName() const const QString &QQmlType::qmlTypeName() const { + if (d->m_name.isEmpty()) { + if (!d->m_module.isEmpty()) + d->m_name = static_cast(d->m_module) + QLatin1Char('/') + d->m_elementName; + else + d->m_name = d->m_elementName; + } + return d->m_name; } diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index c72d2fc..6641a40 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -341,7 +341,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino QQmlPrivate::RegisterType type = { 0, - qRegisterMetaType(pointerName.constData()), 0, 0, 0, + qRegisterNormalizedMetaType(pointerName.constData()), 0, 0, 0, QString(), diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index a3f311e..5206979 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -179,11 +179,13 @@ void tst_qqmlmetatype::qmlType() QVERIFY(type); QVERIFY(type->module() == QLatin1String("Test")); QVERIFY(type->elementName() == QLatin1String("ParserStatusTestType")); + QCOMPARE(type->qmlTypeName(), QLatin1String("Test/ParserStatusTestType")); type = QQmlMetaType::qmlType("Test/ParserStatusTestType", 1, 0); QVERIFY(type); QVERIFY(type->module() == QLatin1String("Test")); QVERIFY(type->elementName() == QLatin1String("ParserStatusTestType")); + QCOMPARE(type->qmlTypeName(), QLatin1String("Test/ParserStatusTestType")); } void tst_qqmlmetatype::isList() -- 1.7.2.5