Optimize QML type registration.
authorMartin Jones <martin.jones@nokia.com>
Fri, 18 May 2012 00:54:09 +0000 (10:54 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 23 May 2012 04:54:25 +0000 (06:54 +0200)
Change-Id: I981f5e2e6d7f6089e9f326d41a65e54668b73120
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
src/qml/qml/qqml.h
src/qml/qml/qqmlmetatype.cpp
src/qml/qml/qqmlvaluetype_p.h
tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp

index b7f5cb7..9c01ee4 100644 (file)
@@ -89,19 +89,30 @@ QT_BEGIN_NAMESPACE
 
 class QQmlPropertyValueInterceptor;
 
+#define QML_GETTYPENAMES \
+    const char *className = T::staticMetaObject.className(); \
+    int nameLen = strlen(className); \
+    QVarLengthArray<char,48> pointerName(nameLen+2); \
+    memcpy(pointerName.data(), className, nameLen); \
+    pointerName[nameLen] = '*'; \
+    pointerName[nameLen+1] = '\0'; \
+    int listLen = strlen("QQmlListProperty<"); \
+    QVarLengthArray<char,64> listName(listLen + nameLen + 2); \
+    memcpy(listName.data(), "QQmlListProperty<", listLen); \
+    memcpy(listName.data()+listLen, className, nameLen); \
+    listName[listLen+nameLen] = '>'; \
+    listName[listLen+nameLen+1] = '\0';
+
 template<typename T>
 int qmlRegisterType()
 {
-    QByteArray name(T::staticMetaObject.className());
-
-    QByteArray pointerName(name + '*');
-    QByteArray listName("QQmlListProperty<" + name + '>');
+    QML_GETTYPENAMES
 
     QQmlPrivate::RegisterType type = {
         0, 
 
-        qRegisterMetaType<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         0, 0,
         QString(),
 
@@ -128,16 +139,13 @@ int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor,
 template<typename T>
 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<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         0, 0,
         reason,
 
@@ -162,16 +170,13 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
 template<typename T>
 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<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         sizeof(T), QQmlPrivate::createInto<T>,
         QString(),
 
@@ -196,16 +201,13 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
 template<typename T, int metaObjectRevision>
 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<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         sizeof(T), QQmlPrivate::createInto<T>,
         QString(),
 
@@ -230,16 +232,13 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
 template<typename T, int metaObjectRevision>
 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<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         sizeof(T), QQmlPrivate::createInto<T>,
         QString(),
 
@@ -265,16 +264,13 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
 template<typename T, typename E>
 int qmlRegisterExtendedType()
 {
-    QByteArray name(T::staticMetaObject.className());
-
-    QByteArray pointerName(name + '*');
-    QByteArray listName("QQmlListProperty<" + name + '>');
+    QML_GETTYPENAMES
 
     QQmlPrivate::RegisterType type = {
         0, 
 
-        qRegisterMetaType<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         0, 0,
         QString(),
 
@@ -300,10 +296,7 @@ template<typename T, typename E>
 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<E>();
     const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>(); 
@@ -315,8 +308,8 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
     QQmlPrivate::RegisterType type = {
         0, 
 
-        qRegisterMetaType<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         sizeof(T), QQmlPrivate::createInto<T>,
         QString(),
 
@@ -349,8 +342,8 @@ int qmlRegisterInterface(const char *typeName)
     QQmlPrivate::RegisterInterface qmlInterface = {
         0,
 
-        qRegisterMetaType<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
 
         qobject_interface_iid<T *>()
     };
@@ -362,16 +355,13 @@ template<typename T>
 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<T *>(pointerName.constData()),
-        qRegisterMetaType<QQmlListProperty<T> >(listName.constData()),
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
         sizeof(T), QQmlPrivate::createInto<T>,
         QString(),
 
index 1566d83..87c39b1 100644 (file)
@@ -190,6 +190,25 @@ public:
     static QHash<const QMetaObject *, int> 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<const QMetaObject *, int> 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<QString>(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<QString>(d->m_module) + QLatin1Char('/') + d->m_elementName;
+        else
+            d->m_name = d->m_elementName;
+    }
+
     return d->m_name;
 }
 
index c72d2fc..6641a40 100644 (file)
@@ -341,7 +341,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino
     QQmlPrivate::RegisterType type = {
         0,
 
-        qRegisterMetaType<T *>(pointerName.constData()), 0, 0, 0,
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, 0, 0,
 
         QString(),
 
index a3f311e..5206979 100644 (file)
@@ -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()