aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativemetatype.cpp
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-07-06 13:43:47 +1000
committerQt by Nokia <qt-info@nokia.com>2011-08-30 13:18:28 +0200
commit809ee66b67ce70dba89a04b92daccc9445af2e75 (patch)
tree84c6d4023312d72583ccfcd2ad79df4fdf714527 /src/declarative/qml/qdeclarativemetatype.cpp
parentf8f9db6cc74a34d3648ac693196c0f5d4bda9c50 (diff)
More efficient type name cache
Instead of creating completely separate hashes for all the types used by every QML file, we simply link to the QDeclarativeTypeModule. This uses much less memory, and is faster to construct at startup. Change-Id: I28bc2807074f9c6f38096d6e4ce8be744159d023 Reviewed-on: http://codereview.qt.nokia.com/3741 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src/declarative/qml/qdeclarativemetatype.cpp')
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp317
1 files changed, 281 insertions, 36 deletions
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index 41705bce72..da7be11545 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -42,9 +42,10 @@
#include <QtDeclarative/qdeclarativeprivate.h>
#include "private/qdeclarativemetatype_p.h"
-#include "private/qdeclarativeproxymetaobject_p.h"
-#include "private/qdeclarativecustomparser_p.h"
-#include "private/qdeclarativeguard_p.h"
+#include <private/qdeclarativeproxymetaobject_p.h>
+#include <private/qdeclarativecustomparser_p.h>
+#include <private/qdeclarativeguard_p.h>
+#include <private/qhashedstring_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -99,6 +100,21 @@ struct QDeclarativeMetaTypeData
MetaObjects metaObjectToType;
typedef QHash<int, QDeclarativeMetaType::StringConverter> StringConverters;
StringConverters stringConverters;
+
+ struct VersionedUri {
+ VersionedUri()
+ : majorVersion(0) {}
+ VersionedUri(const QByteArray &uri, int majorVersion)
+ : uri(uri), majorVersion(majorVersion) {}
+ bool operator==(const VersionedUri &other) const {
+ return other.majorVersion == majorVersion && other.uri == uri;
+ }
+ QByteArray uri;
+ int majorVersion;
+ };
+ typedef QHash<VersionedUri, QDeclarativeTypeModule *> TypeModules;
+ TypeModules uriToModule;
+
struct ModuleApiList {
ModuleApiList() : sorted(true) {}
QList<QDeclarativeMetaType::ModuleApi> moduleApis;
@@ -108,26 +124,38 @@ struct QDeclarativeMetaTypeData
ModuleApis moduleApis;
int moduleApiCount;
- struct ModuleInfo {
- ModuleInfo(int major, int minor)
- : vmajor(major), vminor_min(minor), vminor_max(minor) {}
- ModuleInfo(int major, int minor_min, int minor_max)
- : vmajor(major), vminor_min(minor_min), vminor_max(minor_max) {}
- int vmajor;
- int vminor_min, vminor_max;
- };
- typedef QHash<QPair<QByteArray,int>, ModuleInfo> ModuleInfoHash;
- ModuleInfoHash modules;
-
QBitArray objects;
QBitArray interfaces;
QBitArray lists;
QList<QDeclarativePrivate::AutoParentFunction> parentFunctions;
};
+
+class QDeclarativeTypeModulePrivate
+{
+public:
+ QDeclarativeTypeModulePrivate()
+ : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
+
+ QDeclarativeMetaTypeData::VersionedUri uri;
+
+ int minMinorVersion;
+ int maxMinorVersion;
+
+ void add(QDeclarativeType *);
+
+ QStringHash<QList<QDeclarativeType *> > typeHash;
+ QList<QDeclarativeType *> types;
+};
+
Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData)
Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+static uint qHash(const QDeclarativeMetaTypeData::VersionedUri &v)
+{
+ return qHash(v.uri) ^ qHash(v.majorVersion);
+}
+
QDeclarativeMetaTypeData::QDeclarativeMetaTypeData()
: moduleApiCount(0)
{
@@ -145,11 +173,13 @@ public:
QDeclarativeTypePrivate();
void init() const;
+ void initEnums() const;
bool m_isInterface : 1;
const char *m_iid;
QByteArray m_module;
QByteArray m_name;
+ QString m_elementName;
int m_version_maj;
int m_version_min;
int m_typeId; int m_listId;
@@ -173,8 +203,10 @@ public:
int m_index;
QDeclarativeCustomParser *m_customParser;
mutable volatile bool m_isSetup:1;
- mutable bool m_haveSuperType : 1;
+ mutable volatile bool m_isEnumSetup:1;
+ mutable bool m_haveSuperType:1;
mutable QList<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QStringHash<int> m_enums;
static QHash<const QMetaObject *, int> m_attachedPropertyIds;
};
@@ -186,7 +218,7 @@ QDeclarativeTypePrivate::QDeclarativeTypePrivate()
m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0),
m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1),
m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0),
- m_isSetup(false), m_haveSuperType(false)
+ m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false)
{
}
@@ -268,11 +300,13 @@ int QDeclarativeType::minorVersion() const
bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const
{
+ Q_ASSERT(vmajor >= 0 && vminor >= 0);
return vmajor == d->m_version_maj && vminor >= d->m_version_min;
}
bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const
{
+ Q_ASSERT(vmajor >= 0 && vminor >= 0);
return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
}
@@ -431,6 +465,27 @@ void QDeclarativeTypePrivate::init() const
lock.unlock();
}
+void QDeclarativeTypePrivate::initEnums() const
+{
+ if (m_isEnumSetup) return;
+
+ init();
+
+ QWriteLocker lock(metaTypeDataLock());
+ if (m_isEnumSetup) return;
+
+ const QMetaObject *metaObject = m_baseMetaObject;
+ for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
+
+ QMetaEnum e = metaObject->enumerator(ii);
+
+ for (int jj = 0; jj < e.keyCount(); ++jj)
+ m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
+ }
+
+ m_isEnumSetup = true;
+}
+
QByteArray QDeclarativeType::typeName() const
{
if (d->m_baseMetaObject)
@@ -439,6 +494,16 @@ QByteArray QDeclarativeType::typeName() const
return QByteArray();
}
+const QString &QDeclarativeType::elementName() const
+{
+ if (d->m_elementName.isEmpty()) {
+ QByteArray n = qmlTypeName();
+ int idx = n.lastIndexOf('/');
+ d->m_elementName = QString::fromUtf8(n.mid(idx + 1));
+ }
+ return d->m_elementName;
+}
+
QByteArray QDeclarativeType::qmlTypeName() const
{
return d->m_name;
@@ -591,6 +656,164 @@ int QDeclarativeType::index() const
return d->m_index;
}
+int QDeclarativeType::enumValue(const QHashedStringRef &name) const
+{
+ d->initEnums();
+
+ int *rv = d->m_enums.value(name);
+ return rv?*rv:-1;
+}
+
+int QDeclarativeType::enumValue(const QHashedV8String &name) const
+{
+ d->initEnums();
+
+ int *rv = d->m_enums.value(name);
+ return rv?*rv:-1;
+}
+
+QDeclarativeTypeModule::QDeclarativeTypeModule()
+: d(new QDeclarativeTypeModulePrivate)
+{
+}
+
+QDeclarativeTypeModule::~QDeclarativeTypeModule()
+{
+ delete d; d = 0;
+}
+
+QByteArray QDeclarativeTypeModule::module() const
+{
+ return d->uri.uri;
+}
+
+int QDeclarativeTypeModule::majorVersion() const
+{
+ return d->uri.majorVersion;
+}
+
+int QDeclarativeTypeModule::minimumMinorVersion() const
+{
+ return d->minMinorVersion;
+}
+
+int QDeclarativeTypeModule::maximumMinorVersion() const
+{
+ return d->maxMinorVersion;
+}
+
+void QDeclarativeTypeModulePrivate::add(QDeclarativeType *type)
+{
+ types << type;
+
+ minMinorVersion = qMin(minMinorVersion, type->minorVersion());
+ maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
+
+ QList<QDeclarativeType *> &list = typeHash[type->elementName()];
+ for (int ii = 0; ii < list.count(); ++ii) {
+ if (list.at(ii)->minorVersion() < type->minorVersion()) {
+ list.insert(ii, type);
+ return;
+ }
+ }
+ list.append(type);
+}
+
+QList<QDeclarativeType *> QDeclarativeTypeModule::types()
+{
+ QList<QDeclarativeType *> rv;
+ QReadLocker lock(metaTypeDataLock());
+ rv = d->types;
+ return rv;
+}
+
+QList<QDeclarativeType *> QDeclarativeTypeModule::type(const QString &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QList<QDeclarativeType *> rv;
+ for (int ii = 0; ii < d->types.count(); ++ii) {
+ if (d->types.at(ii)->elementName() == name)
+ rv << d->types.at(ii);
+ }
+ return rv;
+}
+
+QDeclarativeType *QDeclarativeTypeModule::type(const QHashedStringRef &name, int minor)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QList<QDeclarativeType *> *types = d->typeHash.value(name);
+ if (!types) return 0;
+
+ for (int ii = 0; ii < types->count(); ++ii)
+ if (types->at(ii)->minorVersion() <= minor)
+ return types->at(ii);
+
+ return 0;
+}
+
+QDeclarativeType *QDeclarativeTypeModule::type(const QHashedV8String &name, int minor)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QList<QDeclarativeType *> *types = d->typeHash.value(name);
+ if (!types) return 0;
+
+ for (int ii = 0; ii < types->count(); ++ii)
+ if (types->at(ii)->minorVersion() <= minor)
+ return types->at(ii);
+
+ return 0;
+}
+
+
+QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion()
+: m_module(0), m_minor(0)
+{
+}
+
+QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *module, int minor)
+: m_module(module), m_minor(minor)
+{
+ Q_ASSERT(m_module);
+ Q_ASSERT(m_minor >= 0);
+}
+
+QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &o)
+: m_module(o.m_module), m_minor(o.m_minor)
+{
+}
+
+QDeclarativeTypeModuleVersion &QDeclarativeTypeModuleVersion::operator=(const QDeclarativeTypeModuleVersion &o)
+{
+ m_module = o.m_module;
+ m_minor = o.m_minor;
+ return *this;
+}
+
+QDeclarativeTypeModule *QDeclarativeTypeModuleVersion::module() const
+{
+ return m_module;
+}
+
+int QDeclarativeTypeModuleVersion::minorVersion() const
+{
+ return m_minor;
+}
+
+QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedStringRef &name) const
+{
+ if (m_module) return m_module->type(name, m_minor);
+ else return 0;
+}
+
+QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedV8String &name) const
+{
+ if (m_module) return m_module->type(name, m_minor);
+ else return 0;
+}
+
+
int registerAutoParentFunction(QDeclarativePrivate::RegisterAutoParent &autoparent)
{
QWriteLocker lock(metaTypeDataLock());
@@ -665,20 +888,15 @@ int registerType(const QDeclarativePrivate::RegisterType &type)
if (type.uri) {
QByteArray mod(type.uri);
- QPair<QByteArray,int> key(mod,type.versionMajor);
- QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(key);
- if (it == data->modules.end()) {
- // New module
- data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo(type.versionMajor,type.versionMinor));
- } else {
- if ((*it).vminor_max < type.versionMinor) {
- // Newer module
- data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, (*it).vminor_min, type.versionMinor));
- } else if ((*it).vminor_min > type.versionMinor) {
- // Older module
- data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, type.versionMinor, (*it).vminor_min));
- }
+
+ QDeclarativeMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
+ QDeclarativeTypeModule *module = data->uriToModule.value(versionedUri);
+ if (!module) {
+ module = new QDeclarativeTypeModule;
+ module->d->uri = versionedUri;
+ data->uriToModule.insert(versionedUri, module);
}
+ module->d->add(dtype);
}
return index;
@@ -745,6 +963,23 @@ bool QDeclarativeMetaType::isAnyModule(const QByteArray &module)
}
/*
+ Returns true if a module \a uri of any version is installed.
+*/
+bool QDeclarativeMetaType::isAnyModule(const QByteArray &uri)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QDeclarativeMetaTypeData *data = metaTypeData();
+
+ for (QDeclarativeMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
+ iter != data->uriToModule.end(); ++iter) {
+ if ((*iter)->module() == uri)
+ return true;
+ }
+
+ return false;
+}
+
+/*
Returns true if any type or API has been registered for the given \a module with at least
versionMajor.versionMinor, or if types have been registered for \a module with at most
versionMajor.versionMinor.
@@ -753,25 +988,33 @@ bool QDeclarativeMetaType::isAnyModule(const QByteArray &module)
*/
bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor)
{
+ Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
+ QReadLocker lock(metaTypeDataLock());
+
QDeclarativeMetaTypeData *data = metaTypeData();
// first, check Types
- QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(QPair<QByteArray,int>(module,versionMajor));
- if (it != data->modules.end()) {
- if (((*it).vminor_max >= versionMinor && (*it).vminor_min <= versionMinor))
- return true;
- }
+ QDeclarativeTypeModule *tm =
+ data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(module, versionMajor));
+ if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
+ return true;
// then, check ModuleApis
foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
- if (mApi.major == versionMajor && mApi.minor == versionMinor) {
+ if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
return true;
- }
}
return false;
}
+QDeclarativeTypeModule *QDeclarativeMetaType::typeModule(const QByteArray &uri, int majorVersion)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QDeclarativeMetaTypeData *data = metaTypeData();
+ return data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(uri, majorVersion));
+}
+
QList<QDeclarativePrivate::AutoParentFunction> QDeclarativeMetaType::parentFunctions()
{
QReadLocker lock(metaTypeDataLock());
@@ -1003,6 +1246,7 @@ QDeclarativeMetaType::StringConverter QDeclarativeMetaType::customStringConverte
*/
QDeclarativeType *QDeclarativeMetaType::qmlType(const QByteArray &name, int version_major, int version_minor)
{
+ Q_ASSERT(version_major >= 0 && version_minor >= 0);
QReadLocker lock(metaTypeDataLock());
QDeclarativeMetaTypeData *data = metaTypeData();
@@ -1034,6 +1278,7 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject)
*/
QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor)
{
+ Q_ASSERT(version_major >= 0 && version_minor >= 0);
QReadLocker lock(metaTypeDataLock());
QDeclarativeMetaTypeData *data = metaTypeData();