aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2015-04-10 14:56:24 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-04-16 17:14:15 +0000
commit496ddbfd1fe27bdddf5c15cd0ea70df452a3ec04 (patch)
tree779aece69688317cf41c2e5757a7d8684054cc52
parentd22db9e458828d403110fa0b9de1ca0c831d7e96 (diff)
Speed up object creation with lots of id name objects
In the common case when objects are referenced by id, we don't need the QQmlContextData's property name cache for the lookup. Instead of bindings we resolve the id to an integer at type compilation time. Therefore we can delay the population of the QQmlContextData's propertyNames until we need it and therefore safe time on startup. Change-Id: I2e8eeb51b1ac92f230059be3467f9a1e00fdbbef Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/qml/qqmlcontext.cpp48
-rw-r--r--src/qml/qml/qqmlcontext_p.h20
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp8
3 files changed, 44 insertions, 32 deletions
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 1005d097d2..e641226b90 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -305,12 +305,10 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
}
}
- if (data->propertyNames.isEmpty())
- data->propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine()->handle()));
-
- int idx = data->propertyNames.value(name);
+ QV4::IdentifierHash<int> &properties = data->propertyNames();
+ int idx = properties.value(name);
if (idx == -1) {
- data->propertyNames.add(name, data->idValueCount + d->propertyValues.count());
+ properties.add(name, data->idValueCount + d->propertyValues.count());
d->propertyValues.append(value);
data->refreshExpressions();
@@ -343,12 +341,11 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value)
return;
}
- if (data->propertyNames.isEmpty())
- data->propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine()->handle()));
- int idx = data->propertyNames.value(name);
+ QV4::IdentifierHash<int> &properties = data->propertyNames();
+ int idx = properties.value(name);
if (idx == -1) {
- data->propertyNames.add(name, data->idValueCount + d->propertyValues.count());
+ properties.add(name, data->idValueCount + d->propertyValues.count());
d->propertyValues.append(QVariant::fromValue(value));
data->refreshExpressions();
@@ -370,8 +367,9 @@ QVariant QQmlContext::contextProperty(const QString &name) const
QQmlContextData *data = d->data;
- if (data->propertyNames.count())
- idx = data->propertyNames.value(name);
+ const QV4::IdentifierHash<int> &properties = data->propertyNames();
+ if (properties.count())
+ idx = properties.value(name);
if (idx == -1) {
if (data->contextObject) {
@@ -764,31 +762,29 @@ void QQmlContextData::setIdProperty(int idx, QObject *obj)
void QQmlContextData::setIdPropertyData(const QVector<ObjectIdMapping> &data)
{
- Q_ASSERT(propertyNames.isEmpty());
- propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
- for (QVector<ObjectIdMapping>::ConstIterator it = data.begin(), end = data.end();
- it != end; ++it)
- propertyNames.add(it->name, it->id);
-
+ Q_ASSERT(idObjectNames.isEmpty());
+ idObjectNames = data;
+ Q_ASSERT(propertyNameCache.isEmpty());
idValueCount = data.count();
idValues = new ContextGuard[idValueCount];
}
QString QQmlContextData::findObjectId(const QObject *obj) const
{
- if (propertyNames.isEmpty())
+ const QV4::IdentifierHash<int> &properties = propertyNames();
+ if (propertyNameCache.isEmpty())
return QString();
for (int ii = 0; ii < idValueCount; ii++) {
if (idValues[ii] == obj)
- return propertyNames.findId(ii);
+ return properties.findId(ii);
}
if (publicContext) {
QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext);
for (int ii = 0; ii < p->propertyValues.count(); ++ii)
if (p->propertyValues.at(ii) == QVariant::fromValue((QObject *)obj))
- return propertyNames.findId(ii);
+ return properties.findId(ii);
}
if (linkedContext)
@@ -808,4 +804,16 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
return QQmlContextPrivate::get(asQQmlContext());
}
+QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
+{
+ if (propertyNameCache.isEmpty()) {
+ propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
+ for (QVector<ObjectIdMapping>::ConstIterator it = idObjectNames.begin(), end = idObjectNames.end();
+ it != end; ++it)
+ propertyNameCache.add(it->name, it->id);
+ idObjectNames.clear();
+ }
+ return propertyNameCache;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f0e0ab26c6..ddf7d5de75 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -144,8 +144,17 @@ public:
// Compilation unit for contexts that belong to a compiled type.
QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit;
- // Property name cache
- QV4::IdentifierHash<int> propertyNames;
+ struct ObjectIdMapping {
+ ObjectIdMapping() : id(-1) {}
+ ObjectIdMapping(const QString &name, int id)
+ : name(name), id(id) {}
+ QString name;
+ int id;
+ };
+
+ mutable QVector<ObjectIdMapping> idObjectNames;
+ mutable QV4::IdentifierHash<int> propertyNameCache;
+ QV4::IdentifierHash<int> &propertyNames() const;
// Context object
QObject *contextObject;
@@ -188,13 +197,6 @@ public:
QFlagPointer<QQmlContextData> context;
QQmlNotifier bindings;
};
- struct ObjectIdMapping {
- ObjectIdMapping() : id(-1) {}
- ObjectIdMapping(const QString &name, int id)
- : name(name), id(id) {}
- QString name;
- int id;
- };
ContextGuard *idValues;
int idValueCount;
void setIdProperty(int, QObject *);
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 2498e5acc9..7aca9ad6c2 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -199,8 +199,9 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
while (context) {
// Search context properties
- if (context->propertyNames.count()) {
- int propertyIdx = context->propertyNames.value(name);
+ const QV4::IdentifierHash<int> &properties = context->propertyNames();
+ if (properties.count()) {
+ int propertyIdx = properties.value(name);
if (propertyIdx != -1) {
@@ -308,8 +309,9 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
QObject *scopeObject = wrapper->getScopeObject();
while (context) {
+ const QV4::IdentifierHash<int> &properties = context->propertyNames();
// Search context properties
- if (context->propertyNames.count() && -1 != context->propertyNames.value(name))
+ if (properties.count() && properties.value(name) != -1)
return;
// Search scope object