summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2010-01-09 09:09:15 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2010-01-09 09:09:15 (GMT)
commit41f7ccb2dd21dcd4b0f2aa172bb813095cb2ade3 (patch)
tree60746e15deeb1ca5c2ff6f0f096bc96c6aeef6aa
parent3ade772efd07fe342c10274b5fc6387965ac0c9d (diff)
downloadQt-41f7ccb2dd21dcd4b0f2aa172bb813095cb2ade3.zip
Qt-41f7ccb2dd21dcd4b0f2aa172bb813095cb2ade3.tar.gz
Qt-41f7ccb2dd21dcd4b0f2aa172bb813095cb2ade3.tar.bz2
Optimization: Bypass qt_metacall for synthesized methods
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp5
-rw-r--r--src/declarative/qml/qmlcompiler.cpp19
-rw-r--r--src/declarative/qml/qmlcompiler_p.h2
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp11
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp81
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h20
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp50
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h4
8 files changed, 163 insertions, 29 deletions
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp
index 198b574..de9bf96 100644
--- a/src/declarative/qml/qmlcompileddata.cpp
+++ b/src/declarative/qml/qmlcompileddata.cpp
@@ -162,7 +162,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
}
QmlCompiledData::QmlCompiledData()
-: importCache(0), root(0)
+: importCache(0), root(0), rootPropertyCache(0)
{
}
@@ -182,6 +182,9 @@ QmlCompiledData::~QmlCompiledData()
if (importCache)
importCache->release();
+ if (rootPropertyCache)
+ rootPropertyCache->release();
+
qDeleteAll(cachedPrograms);
qDeleteAll(cachedClosures);
}
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 7c43305..7f8bc7a 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -90,7 +90,7 @@ using namespace QmlParser;
Instantiate a new QmlCompiler.
*/
QmlCompiler::QmlCompiler()
-: output(0), engine(0)
+: output(0), engine(0), unitRoot(0), unit(0)
{
}
@@ -611,6 +611,7 @@ bool QmlCompiler::compile(QmlEngine *engine,
this->engine = engine;
this->unit = unit;
+ this->unitRoot = root;
compileTree(root);
if (!isError()) {
@@ -626,6 +627,8 @@ bool QmlCompiler::compile(QmlEngine *engine,
savedCompileStates.clear();
output = 0;
this->engine = 0;
+ this->unit = 0;
+ this->unitRoot = 0;
return !isError();
}
@@ -836,7 +839,19 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata);
meta.storeMeta.propertyCache = output->propertyCaches.count();
// ### Surely the creation of this property cache could be more efficient
- output->propertyCaches << QmlPropertyCache::create(engine, obj->metaObject());
+ QmlPropertyCache *propertyCache = 0;
+ if (tr.component && QmlComponentPrivate::get(tr.component)->cc->rootPropertyCache) {
+ propertyCache = QmlComponentPrivate::get(tr.component)->cc->rootPropertyCache->copy();
+ } else {
+ propertyCache = QmlPropertyCache::create(engine, obj->metaObject()->superClass());
+ }
+ propertyCache->append(engine, obj->metaObject(), QmlPropertyCache::Data::NoFlags,
+ QmlPropertyCache::Data::IsVMEFunction);
+ if (obj == unitRoot) {
+ propertyCache->addref();
+ output->rootPropertyCache = propertyCache;
+ }
+ output->propertyCaches << propertyCache;
output->bytecode << meta;
}
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 740d97c..c0e50e4 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -107,6 +107,7 @@ public:
const QMetaObject *root;
QAbstractDynamicMetaObject rootData;
+ QmlPropertyCache *rootPropertyCache;
QList<QString> primitives;
QList<float> floatData;
QList<int> intData;
@@ -324,6 +325,7 @@ private:
QList<QmlError> exceptions;
QmlCompiledData *output;
QmlEngine *engine;
+ QmlParser::Object *unitRoot;
QmlCompositeTypeData *unit;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
index 73dfd75..f372561 100644
--- a/src/declarative/qml/qmlobjectscriptclass.cpp
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -48,6 +48,7 @@
#include "qmllistscriptclass_p.h"
#include "qmlbinding.h"
#include "qmlguard_p.h"
+#include "qmlvmemetaobject_p.h"
#include <QtCore/qtimer.h>
@@ -216,9 +217,13 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name
return enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace);
} else if (lastData->flags & QmlPropertyCache::Data::IsFunction) {
- // ### Optimize
- QScriptValue sobj = scriptEngine->newQObject(obj);
- return sobj.property(toString(name));
+ if (lastData->flags & QmlPropertyCache::Data::IsVMEFunction) {
+ return ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex);
+ } else {
+ // ### Optimize
+ QScriptValue sobj = scriptEngine->newQObject(obj);
+ return sobj.property(toString(name));
+ }
} else {
if (enginePriv->captureProperties && !(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
enginePriv->capturedProperties <<
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
index bc7d7de..394fa35 100644
--- a/src/declarative/qml/qmlpropertycache.cpp
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -87,8 +87,8 @@ void QmlPropertyCache::Data::load(const QMetaMethod &m)
}
-QmlPropertyCache::QmlPropertyCache(QmlEngine *engine)
-: QmlCleanup(engine)
+QmlPropertyCache::QmlPropertyCache(QmlEngine *e)
+: QmlCleanup(e), engine(e)
{
}
@@ -145,6 +145,83 @@ QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject,
return rv;
}
+QmlPropertyCache *QmlPropertyCache::copy() const
+{
+ QmlPropertyCache *cache = new QmlPropertyCache(engine);
+ cache->indexCache = indexCache;
+ cache->stringCache = stringCache;
+ cache->identifierCache = identifierCache;
+
+ for (int ii = 0; ii < indexCache.count(); ++ii)
+ indexCache.at(ii)->addref();
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
+ (*iter)->addref();
+ for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter)
+ (*iter)->addref();
+
+ return cache;
+}
+
+void QmlPropertyCache::append(QmlEngine *engine, const QMetaObject *metaObject,
+ Data::Flag propertyFlags, Data::Flag methodFlags)
+{
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ int propCount = metaObject->propertyCount();
+ int propOffset = metaObject->propertyOffset();
+
+ indexCache.resize(propCount);
+ for (int ii = propOffset; ii < propCount; ++ii) {
+ QMetaProperty p = metaObject->property(ii);
+ QString propName = QString::fromUtf8(p.name());
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
+
+ data->load(p, engine);
+ data->flags |= propertyFlags;
+
+ indexCache[ii] = data;
+
+ if (stringCache.contains(propName)) {
+ stringCache[propName]->release();
+ identifierCache[data->identifier.identifier]->release();
+ }
+
+ stringCache.insert(propName, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ int methodCount = metaObject->methodCount();
+ int methodOffset = metaObject->methodOffset();
+ for (int ii = methodOffset; ii < methodCount; ++ii) {
+ QMetaMethod m = metaObject->method(ii);
+ QString methodName = QString::fromUtf8(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
+
+ if (stringCache.contains(methodName)) {
+ stringCache[methodName]->release();
+ identifierCache[data->identifier.identifier]->release();
+ }
+
+ data->load(m);
+ if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method)
+ data->flags |= methodFlags;
+
+ stringCache.insert(methodName, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ }
+}
+
// ### Optimize - check engine for the parent meta object etc.
QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject)
{
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
index 50b4cf2..feaa683 100644
--- a/src/declarative/qml/qmlpropertycache_p.h
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -75,18 +75,21 @@ public:
inline bool operator==(const Data &);
enum Flag {
+ NoFlags = 0x00000000,
+
// Can apply to all properties, except IsFunction
IsConstant = 0x00000001,
IsWritable = 0x00000002,
// These are mutually exclusive
IsFunction = 0x00000004,
- IsQObjectDerived = 0x00000008,
- IsEnumType = 0x00000010,
- IsQmlList = 0x00000020,
- IsQList = 0x00000040,
- IsQmlBinding = 0x00000080,
- IsQScriptValue = 0x00000100
+ IsVMEFunction = 0x00000008,
+ IsQObjectDerived = 0x00000010,
+ IsEnumType = 0x00000020,
+ IsQmlList = 0x00000040,
+ IsQList = 0x00000080,
+ IsQmlBinding = 0x00000100,
+ IsQScriptValue = 0x00000200
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -112,6 +115,10 @@ public:
void update(QmlEngine *, const QMetaObject *);
+ QmlPropertyCache *copy() const;
+ void append(QmlEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags,
+ Data::Flag methodFlags = Data::NoFlags);
+
static QmlPropertyCache *create(QmlEngine *, const QMetaObject *);
static Data create(const QMetaObject *, const QString &);
@@ -131,6 +138,7 @@ private:
typedef QHash<QString, RData *> StringCache;
typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ QmlEngine *engine;
IndexCache indexCache;
StringCache stringCache;
IdentifierCache identifierCache;
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
index fd699c3..c863ffd 100644
--- a/src/declarative/qml/qmlvmemetaobject.cpp
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -265,27 +265,16 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine());
- if (!methods)
- methods = new QScriptValue[metaData->methodCount];
-
- QmlVMEMetaData::MethodData *data = metaData->methodData() + id;
- if (!methods[id].isValid()) {
- const QChar *body =
- (const QChar *)(((const char*)metaData) + data->bodyOffset);
-
- QString code = QString::fromRawData(body, data->bodyLength);
-
- // XXX Use QScriptProgram
- methods[id] = QmlExpressionPrivate::evalInObjectScope(ctxt, object, code);
- }
+ QScriptValue function = method(id);
QScriptValueList args;
+ QmlVMEMetaData::MethodData *data = metaData->methodData() + id;
if (data->parameterCount) {
for (int ii = 0; ii < data->parameterCount; ++ii) {
args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]);
}
}
- QScriptValue rv = methods[id].call(ep->scriptEngine.globalObject(), args);
+ QScriptValue rv = function.call(ep->objectClass->newQObject(object), args);
if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv);
@@ -301,6 +290,29 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
return object->qt_metacall(c, _id, a);
}
+QScriptValue QmlVMEMetaObject::method(int index)
+{
+ if (!methods)
+ methods = new QScriptValue[metaData->methodCount];
+
+ if (!methods[index].isValid()) {
+ QmlVMEMetaData::MethodData *data = metaData->methodData() + index;
+
+ const QChar *body =
+ (const QChar *)(((const char*)metaData) + data->bodyOffset);
+
+ QString code = QString::fromRawData(body, data->bodyLength);
+
+ // XXX Use QScriptProgram
+ // XXX We should evaluate all methods in a single big script block to
+ // improve the call time between dynamic methods defined on the same
+ // object
+ methods[index] = QmlExpressionPrivate::evalInObjectScope(ctxt, object, code);
+ }
+
+ return methods[index];
+}
+
void QmlVMEMetaObject::listChanged(int id)
{
activate(object, methodOffset + id, 0);
@@ -314,5 +326,15 @@ void QmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QmlPropert
interceptors.insert(index, qMakePair(valueIndex, interceptor));
}
+QScriptValue QmlVMEMetaObject::vmeMethod(int index)
+{
+ if (index < methodOffset) {
+ Q_ASSERT(parent);
+ return static_cast<QmlVMEMetaObject *>(parent)->vmeMethod(index);
+ }
+ int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
+ Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + metaData->methodCount));
+ return method(index - methodOffset - plainSignals);
+}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
index b79e42c..497d8f6 100644
--- a/src/declarative/qml/qmlvmemetaobject_p.h
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -114,7 +114,7 @@ public:
~QmlVMEMetaObject();
void registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor);
-
+ QScriptValue vmeMethod(int index);
protected:
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
@@ -131,7 +131,9 @@ private:
QBitArray aConnected;
QBitArray aInterceptors;
QHash<int, QPair<int, QmlPropertyValueInterceptor*> > interceptors;
+
QScriptValue *methods;
+ QScriptValue method(int);
QAbstractDynamicMetaObject *parent;