summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-06-10 05:03:29 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-06-10 05:03:29 (GMT)
commit6b88d7152a72a3a6ba12cb6b4eeeecc1a0c24c51 (patch)
treef4a61bb049df2d3c83ce50bcd85b9772fc115251 /src/declarative/qml
parent5c24620b91ee57629b4356885f8b5517e3d82e32 (diff)
downloadQt-6b88d7152a72a3a6ba12cb6b4eeeecc1a0c24c51.zip
Qt-6b88d7152a72a3a6ba12cb6b4eeeecc1a0c24c51.tar.gz
Qt-6b88d7152a72a3a6ba12cb6b4eeeecc1a0c24c51.tar.bz2
Improve list assignment performance
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qmlcompiler.cpp68
-rw-r--r--src/declarative/qml/qmlcompiler_p.h2
-rw-r--r--src/declarative/qml/qmlinstruction_p.h4
-rw-r--r--src/declarative/qml/qmlvme.cpp110
4 files changed, 120 insertions, 64 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 04a488d..16e1b13 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -1091,7 +1091,9 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
fetch.line = prop->location.start.line;
fetch.type = QmlInstruction::FetchQmlList;
fetch.fetchQmlList.property = prop->index;
- fetch.fetchQmlList.type = QmlMetaType::qmlListType(t);
+ int listType = QmlMetaType::qmlListType(t);
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+ fetch.fetchQmlList.type = listType;
output->bytecode << fetch;
for (int ii = 0; ii < prop->values.count(); ++ii) {
@@ -1099,10 +1101,23 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
if (v->object) {
v->type = Value::CreatedObject;
COMPILE_CHECK(compileObject(v->object, ctxt));
- QmlInstruction assign;
- assign.type = QmlInstruction::AssignObjectList;
- assign.line = prop->location.start.line;
- output->bytecode << assign;
+
+ if (!listTypeIsInterface) {
+ if (canConvert(listType, v->object)) {
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreObjectQmlList;
+ store.line = prop->location.start.line;
+ output->bytecode << store;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign object to list");
+ }
+
+ } else {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->location.start.line;
+ output->bytecode << assign;
+ }
} else {
COMPILE_EXCEPTION("Cannot assign primitives to lists");
}
@@ -1116,7 +1131,10 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
QmlInstruction fetch;
fetch.type = QmlInstruction::FetchQList;
fetch.line = prop->location.start.line;
- fetch.fetch.property = prop->index;
+ fetch.fetchQmlList.property = prop->index;
+ int listType = QmlMetaType::listType(t);
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+ fetch.fetchQmlList.type = listType;
output->bytecode << fetch;
bool assignedBinding = false;
@@ -1125,10 +1143,22 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
if (v->object) {
v->type = Value::CreatedObject;
COMPILE_CHECK(compileObject(v->object, ctxt));
- QmlInstruction assign;
- assign.type = QmlInstruction::AssignObjectList;
- assign.line = v->location.start.line;
- output->bytecode << assign;
+
+ if (!listTypeIsInterface) {
+ if (canConvert(listType, v->object)) {
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreObjectQList;
+ store.line = prop->location.start.line;
+ output->bytecode << store;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign object to list");
+ }
+ } else {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = v->location.start.line;
+ output->bytecode << assign;
+ }
} else if (v->value.isScript()) {
if (assignedBinding)
COMPILE_EXCEPTION("Can only assign one binding to lists");
@@ -1575,6 +1605,24 @@ void QmlCompiler::finalizeBinding(const BindingReference &binding)
instr.assignBinding.category = QmlMetaProperty::propertyCategory(mp);
}
+/*!
+ Returns true if object can be assigned to a (QObject) property of type
+ convertType.
+*/
+bool QmlCompiler::canConvert(int convertType, QmlParser::Object *object)
+{
+ const QMetaObject *convertTypeMo =
+ QmlMetaType::rawMetaObjectForType(convertType);
+ const QMetaObject *objectMo = object->metaObject();
+
+ while (objectMo) {
+ if (objectMo == convertTypeMo)
+ return true;
+ objectMo = objectMo->superClass();
+ }
+ return false;
+}
+
QmlCompiledData::QmlCompiledData()
{
}
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 6b6d8cb..3b1a496 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -179,6 +179,8 @@ private:
struct BindingReference;
void finalizeBinding(const BindingReference &);
+ bool canConvert(int, QmlParser::Object *);
+
struct IdReference {
QString id;
QmlParser::Object *object;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index bdbbaff..a1d923d 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -105,8 +105,6 @@ public:
StoreSignal, /* storeSignal */
- StoreObjectQmlList,
-
// XXX need to handle storing objects in variants
//
@@ -122,6 +120,8 @@ public:
BeginObject, /* begin */
CompleteObject, /* complete */
+ StoreObjectQmlList, /* NA */
+ StoreObjectQList, /* NA */
AssignObjectList, /* NA */
FetchAttached, /* fetchAttached */
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 9ed7e95..3f7739e 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -87,6 +87,7 @@ Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) {
Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject);
Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal);
Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQList);
Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject);
Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding);
Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding);
@@ -126,6 +127,7 @@ Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") {
Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject");
Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal");
Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQList, "StoreObjectQList");
Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject");
Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding");
Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding");
@@ -171,13 +173,18 @@ QmlVME::QmlVME()
struct ListInstance
{
ListInstance() {}
+ /*
ListInstance(const QVariant &l, int t)
: list(l), type(t), qmlListInterface(0) {}
+ */
+ ListInstance(QList<void *> *q, int t)
+ : type(t), qListInterface(q) {}
ListInstance(QmlPrivate::ListInterface *q, int t)
: type(t), qmlListInterface(q) {}
- QVariant list;
+ //QVariant list;
int type;
+ QList<void *> *qListInterface;
QmlPrivate::ListInterface *qmlListInterface;
};
@@ -737,65 +744,56 @@ case QmlInstruction::StoreDouble:
}
break;
+ case QmlInstruction::StoreObjectQmlList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreObjectQmlList> cc;
+#endif
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+
+ void *d = (void *)&assign;
+ list.qmlListInterface->append(d);
+ }
+ break;
+
+ case QmlInstruction::StoreObjectQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreObjectQList> cc;
+#endif
+ QObject *assign = stack.pop();
+
+ const ListInstance &list = qliststack.top();
+ list.qListInterface->append((void *)assign);
+ }
+ break;
+
case QmlInstruction::AssignObjectList:
{
+ // This is only used for assigning interfaces
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxCompilerTimer<QFxCompiler::InstrAssignObjectList> cc;
#endif
QObject *assign = stack.pop();
const ListInstance &list = qliststack.top();
- if (list.qmlListInterface) {
- int type = list.type;
-
- void *d = 0;
- void *ptr = 0;
- bool found = false;
-
- if (QmlMetaType::isInterface(type)) {
- const char *iid = QmlMetaType::interfaceIId(type);
- if (iid)
- ptr = assign->qt_metacast(iid);
- if (ptr) {
- d = &ptr;
- found = true;
- }
- } else {
- const QMetaObject *mo =
- QmlMetaType::rawMetaObjectForType(type);
-
- const QMetaObject *assignMo = assign->metaObject();
- while(!found && assignMo) {
- if (assignMo == mo)
- found = true;
- else
- assignMo = assignMo->superClass();
- }
-
- // NOTE: This assumes a cast to QObject does not alter
- // the object pointer
- d = (void *)&assign;
- }
+ int type = list.type;
- if (!found)
- VME_EXCEPTION("Cannot assign object to list");
+ void *ptr = 0;
- list.qmlListInterface->append(d);
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ if (!ptr)
+ VME_EXCEPTION("Cannot assign object to list");
+
+ if (list.qmlListInterface) {
+ void *d = (void *)&ptr;
+ list.qmlListInterface->append(d);
} else {
- int type = list.type;
-
- if (QmlMetaType::isInterface(type)) {
- void *ptr = 0;
- const char *iid = QmlMetaType::interfaceIId(type);
- if (iid)
- ptr = assign->qt_metacast(iid);
- QVariant v(list.type, &ptr);
- QmlMetaType::append(list.list, v);
- } else {
- QVariant v = QmlMetaType::fromObject(assign, list.type);
- QmlMetaType::append(list.list, v);
- }
+ list.qListInterface->append(ptr);
}
}
break;
@@ -883,10 +881,18 @@ case QmlInstruction::StoreDouble:
QFxCompilerTimer<QFxCompiler::InstrFetchQList> cc;
#endif
QObject *target = stack.top();
- QMetaProperty prop =
- target->metaObject()->property(instr.fetch.property);
- QVariant v = prop.read(target);
- qliststack.push(ListInstance(v, QmlMetaType::listType(prop.userType())));
+
+ void *a[1];
+ // We know that QList<T *>* can be converted to
+ // QList<void *>*
+ QList<void *> *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION("Cannot assign to null list");
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
}
break;