diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2010-01-08 09:02:10 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2010-01-08 09:02:10 (GMT) |
commit | 8c84f7ca274e5c8e4d249ede904bb247659dbce4 (patch) | |
tree | 58e7553b5a417c87e61cb0ba95319123344d0f32 /src | |
parent | b30af554ba34bddc4f2487f037113c810597cda0 (diff) | |
download | Qt-8c84f7ca274e5c8e4d249ede904bb247659dbce4.zip Qt-8c84f7ca274e5c8e4d249ede904bb247659dbce4.tar.gz Qt-8c84f7ca274e5c8e4d249ede904bb247659dbce4.tar.bz2 |
Optimization: Cache compiled dynamic functions
Diffstat (limited to 'src')
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 15 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext.cpp | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 5 | ||||
-rw-r--r-- | src/declarative/qml/qmlexpression.cpp | 32 | ||||
-rw-r--r-- | src/declarative/qml/qmlexpression_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject.cpp | 61 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject_p.h | 10 |
8 files changed, 81 insertions, 47 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 7f11a23..7c43305 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2341,13 +2341,24 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - const Object::DynamicSlot &s = obj->dynamicSlots.at(ii); + Object::DynamicSlot &s = obj->dynamicSlots[ii]; QByteArray sig(s.name + '('); + QString funcScript(QLatin1String("(function(")); + for (int jj = 0; jj < s.parameterNames.count(); ++jj) { - if (jj) sig.append(','); + if (jj) { + sig.append(','); + funcScript.append(QLatin1Char(',')); + } + funcScript.append(s.parameterNames.at(jj)); sig.append("QVariant"); } sig.append(')'); + funcScript.append(QLatin1Char(')')); + funcScript.append(s.body); + funcScript.append(QLatin1Char(')')); + s.body = funcScript; + QMetaMethodBuilder b = builder.addSlot(sig); b.setReturnType("QVariant"); b.setParameterNames(s.parameterNames); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index e063981..e7ac864 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() -: parent(0), engine(0), isInternal(false), isTemporary(false), propertyNames(0), +: parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1), highPriorityCount(0), imports(0), expressions(0), contextObjects(0), idValues(0), idValueCount(0), optimizedBindings(0) { diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index cb89474..e682ee2 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -88,7 +88,6 @@ public: QmlEngine *engine; bool isInternal; - bool isTemporary; QmlIntegerCache *propertyNames; QList<QVariant> propertyValues; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 708cdd1..19a20e8 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -649,10 +649,7 @@ QmlContext *QmlEnginePrivate::getContext(QScriptContext *ctxt) QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3); Q_ASSERT(scopeNode.isValid()); Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass); - QmlContext *context = contextClass->contextFromValue(scopeNode); - while (context && QmlContextPrivate::get(context)->isTemporary) - context = context->parentContext(); - return context; + return contextClass->contextFromValue(scopeNode); } QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt, diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 1321601..1587d61 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -138,19 +138,13 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, dd->cachedPrograms[progIdx] = new QScriptProgram(data->expression, data->url, data->line); } -#endif - - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); -#if !defined(Q_OS_SYMBIAN) - data->expressionFunction = scriptEngine->evaluate(*dd->cachedPrograms.at(progIdx)); + data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx)); #else - data->expressionFunction = scriptEngine->evaluate(data->expression); + data->expressionFunction = evalInObjectScope(ctxt, me, data->expression); #endif data->expressionFunctionValid = true; - scriptEngine->popContext(); } } @@ -158,6 +152,28 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, data->me = me; } +QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObject *object, + const QString &program) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(context->engine()); + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); + scriptContext->pushScope(ep->contextClass->newContext(context, object)); + QScriptValue rv = ep->scriptEngine.evaluate(program); + ep->scriptEngine.popContext(); + return rv; +} + +QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObject *object, + const QScriptProgram &program) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(context->engine()); + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); + scriptContext->pushScope(ep->contextClass->newContext(context, object)); + QScriptValue rv = ep->scriptEngine.evaluate(program); + ep->scriptEngine.popContext(); + return rv; +} + /*! \class QmlExpression \brief The QmlExpression class evaluates ECMAScript in a QML context. diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 3f87b2f..8561a57 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -164,6 +164,8 @@ public: } static void exceptionToError(QScriptEngine *, QmlError &); + static QScriptValue evalInObjectScope(QmlContext *, QObject *, const QString &); + static QScriptValue evalInObjectScope(QmlContext *, QObject *, const QScriptProgram &); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index 3b1f068..fd699c3 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -44,6 +44,7 @@ #include "qml.h" #include "qmlrefcount_p.h" #include "qmlexpression.h" +#include "qmlexpression_p.h" #include "qmlcontext_p.h" #include <QColor> @@ -56,11 +57,11 @@ QT_BEGIN_NAMESPACE QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QmlVMEMetaData *meta, - QmlRefCount *rc) -: object(obj), ref(rc), ctxt(qmlContext(obj)), metaData(meta), parent(0) + QmlCompiledData *cdata) +: object(obj), compiledData(cdata), ctxt(qmlContext(obj)), metaData(meta), methods(0), + parent(0) { - if (ref) - ref->addref(); + compiledData->addref(); *static_cast<QMetaObject *>(this) = *other; this->d.superdata = obj->metaObject(); @@ -91,12 +92,11 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, QmlVMEMetaObject::~QmlVMEMetaObject() { - if (ref) - ref->release(); - if (parent) - delete parent; + compiledData->release(); + delete parent; qDeleteAll(listProperties); delete [] data; + delete [] methods; } int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) @@ -260,29 +260,36 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) id -= plainSignals; if (id < metaData->methodCount) { + if (!ctxt->engine()) + return -1; // We can't run the method + + QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine()); + + if (!methods) + methods = new QScriptValue[metaData->methodCount]; + QmlVMEMetaData::MethodData *data = metaData->methodData() + id; - const QChar *body = - (const QChar *)(((const char*)metaData) + data->bodyOffset); + if (!methods[id].isValid()) { + const QChar *body = + (const QChar *)(((const char*)metaData) + data->bodyOffset); - QString code = QString::fromRawData(body, data->bodyLength); + QString code = QString::fromRawData(body, data->bodyLength); - QVariant rv; - if (0 == (metaData->methodData() + id)->parameterCount) { - QmlExpression expr(ctxt, code, object); - expr.setTrackChange(false); - rv = expr.value(); - } else { - QmlContext newCtxt(ctxt); - QmlContextPrivate::get(&newCtxt)->isTemporary = true; - QMetaMethod m = method(_id); - QList<QByteArray> names = m.parameterNames(); - for (int ii = 0; ii < names.count(); ++ii) - newCtxt.setContextProperty(QString::fromLatin1(names.at(ii)), *(QVariant *)a[ii + 1]); - QmlExpression expr(&newCtxt, code, object); - expr.setTrackChange(false); - rv = expr.value(); + // XXX Use QScriptProgram + methods[id] = QmlExpressionPrivate::evalInObjectScope(ctxt, object, code); } - if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = rv; + + QScriptValueList args; + 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); + + if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv); + + return -1; } return -1; } diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 462f652..b79e42c 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -62,6 +62,7 @@ #include <private/qobject_p.h> #include "qmlguard_p.h" +#include "qmlcompiler_p.h" QT_BEGIN_NAMESPACE @@ -88,7 +89,7 @@ struct QmlVMEMetaData int parameterCount; int bodyOffset; int bodyLength; - int _dummy; + int scriptProgram; }; PropertyData *propertyData() const { @@ -108,8 +109,8 @@ class QmlRefCount; class QmlVMEMetaObject : public QAbstractDynamicMetaObject { public: - QmlVMEMetaObject(QObject *, const QMetaObject *, const QmlVMEMetaData *data, - QmlRefCount * = 0); + QmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QmlVMEMetaData *data, + QmlCompiledData *compiledData); ~QmlVMEMetaObject(); void registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor); @@ -119,7 +120,7 @@ protected: private: QObject *object; - QmlRefCount *ref; + QmlCompiledData *compiledData; QmlGuard<QmlContext> ctxt; const QmlVMEMetaData *metaData; @@ -130,6 +131,7 @@ private: QBitArray aConnected; QBitArray aInterceptors; QHash<int, QPair<int, QmlPropertyValueInterceptor*> > interceptors; + QScriptValue *methods; QAbstractDynamicMetaObject *parent; |