summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlengine.cpp15
-rw-r--r--src/declarative/qml/qmlengine_p.h3
-rw-r--r--src/declarative/qml/qmlexpression.cpp3
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp37
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h2
-rw-r--r--tests/benchmarks/declarative/script/script.pro11
-rw-r--r--tests/benchmarks/declarative/script/tst_script.cpp451
7 files changed, 510 insertions, 12 deletions
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index e7d0743..708cdd1 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -117,11 +117,11 @@ struct StaticQtMetaObject : public QObject
};
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
-: rootContext(0), currentExpression(0),
- isDebugging(false), contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0), globalClass(0),
- cleanup(0), erroredBindings(0),
- inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttacheds(0),
- inBeginCreate(false), networkAccessManager(0), typeManager(e), uniqueId(1)
+: captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false),
+ contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0),
+ globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0),
+ scriptEngine(this), workerScriptEngine(0), componentAttacheds(0), inBeginCreate(false),
+ networkAccessManager(0), typeManager(e), uniqueId(1)
{
globalClass = new QmlGlobalScriptClass(&scriptEngine);
fileImportPath.append(QLibraryInfo::location(QLibraryInfo::DataPath)+QDir::separator()+QLatin1String("qml"));
@@ -138,10 +138,7 @@ QUrl QmlScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
}
QmlScriptEngine::QmlScriptEngine(QmlEnginePrivate *priv)
- : p(priv),
- sqlQueryClass(0),
- namedNodeMapClass(0),
- nodeListClass(0)
+: p(priv), sqlQueryClass(0), namedNodeMapClass(0), nodeListClass(0)
{
// Note that all documentation for stuff put on the global object goes in
// doc/src/declarative/globalobject.qdoc
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 8f2f0fb..2f177a2 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -127,7 +127,7 @@ public:
QUrl baseUrl;
};
-class QmlEnginePrivate : public QObjectPrivate
+class Q_AUTOTEST_EXPORT QmlEnginePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QmlEngine)
public:
@@ -144,6 +144,7 @@ public:
int coreIndex;
int notifyIndex;
};
+ bool captureProperties;
QPODVector<CapturedProperty> capturedProperties;
QmlContext *rootContext;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index 652c5f8..1321601 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -436,10 +436,12 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
QmlEnginePrivate *ep = QmlEnginePrivate::get(q->engine());
QmlExpression *lastCurrentExpression = ep->currentExpression;
+ bool lastCaptureProperties = ep->captureProperties;
QPODVector<QmlEnginePrivate::CapturedProperty> lastCapturedProperties;
ep->capturedProperties.copyAndClear(lastCapturedProperties);
ep->currentExpression = q;
+ ep->captureProperties = data->trackChange;
// This object might be deleted during the eval
QmlExpressionData *localData = data;
@@ -452,6 +454,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
}
ep->currentExpression = lastCurrentExpression;
+ ep->captureProperties = lastCaptureProperties;
// Check if we were deleted
if (localData->q) {
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
index 7f95b8f..73dfd75 100644
--- a/src/declarative/qml/qmlobjectscriptclass.cpp
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -220,7 +220,7 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name
QScriptValue sobj = scriptEngine->newQObject(obj);
return sobj.property(toString(name));
} else {
- if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
+ if (enginePriv->captureProperties && !(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
enginePriv->capturedProperties <<
QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
}
@@ -247,6 +247,41 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name
void *args[] = { &rv, 0 };
QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
return rv;
+ } else if (lastData->propType == QMetaType::QReal) {
+ qreal rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
+ } else if (lastData->propType == QMetaType::Int) {
+ int rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
+ } else if (lastData->propType == QMetaType::Bool) {
+ bool rv = false;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
+ } else if (lastData->propType == QMetaType::QString) {
+ QString rv;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
+ } else if (lastData->propType == QMetaType::UInt) {
+ uint rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
+ } else if (lastData->propType == QMetaType::Float) {
+ float rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
+ } else if (lastData->propType == QMetaType::Double) {
+ double rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return QScriptValue(rv);
} else {
QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
return enginePriv->scriptValueFromVariant(var);
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
index 923be73..ca50688 100644
--- a/src/declarative/qml/qmlobjectscriptclass_p.h
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -66,7 +66,7 @@ class QmlEngine;
class QScriptContext;
class QScriptEngine;
class QmlContext;
-class QmlObjectScriptClass : public QScriptDeclarativeClass
+class Q_AUTOTEST_EXPORT QmlObjectScriptClass : public QScriptDeclarativeClass
{
public:
QmlObjectScriptClass(QmlEngine *);
diff --git a/tests/benchmarks/declarative/script/script.pro b/tests/benchmarks/declarative/script/script.pro
new file mode 100644
index 0000000..48fea81
--- /dev/null
+++ b/tests/benchmarks/declarative/script/script.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_script
+QT += declarative script
+macx:CONFIG -= app_bundle
+CONFIG += release
+
+SOURCES += tst_script.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
diff --git a/tests/benchmarks/declarative/script/tst_script.cpp b/tests/benchmarks/declarative/script/tst_script.cpp
new file mode 100644
index 0000000..2aa7a9f
--- /dev/null
+++ b/tests/benchmarks/declarative/script/tst_script.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QmlEngine>
+#include <private/qmlengine_p.h>
+#include <private/qmlobjectscriptclass_p.h>
+#include <QScriptEngine>
+#include <QScriptValue>
+
+class tst_script : public QObject
+{
+ Q_OBJECT
+public:
+ tst_script() {}
+
+private slots:
+ void property_js();
+ void property_getter();
+ void property_getter_js();
+ void property_getter_qobject();
+ void property_getter_qmetaproperty();
+ void property_qobject();
+ void property_qmlobject();
+
+ void function_js();
+ void function_cpp();
+ void function_qobject();
+ void function_qmlobject();
+
+ void function_args_js();
+ void function_args_cpp();
+ void function_args_qobject();
+ void function_args_qmlobject();
+
+private:
+};
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x)
+
+public:
+ TestObject(QObject *parent = 0);
+
+ int x();
+
+public slots:
+ int method() {
+ return x();
+ }
+
+ int methodArgs(int val) {
+ return val + x();
+ }
+
+private:
+ int m_x;
+};
+
+TestObject::TestObject(QObject *parent)
+: QObject(parent), m_x(0)
+{
+}
+
+int TestObject::x()
+{
+ return m_x++;
+}
+
+#define PROPERTY_PROGRAM \
+ "(function(testObject) { return (function() { " \
+ " var test = 0; " \
+ " for (var ii = 0; ii < 10000; ++ii) { " \
+ " test += testObject.x; " \
+ " } " \
+ " return test; " \
+ "}); })"
+
+void tst_script::property_js()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.newObject();
+ v.setProperty(QLatin1String("x"), 10);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call().toNumber();
+ }
+}
+
+static QScriptValue property_getter_method(QScriptContext *, QScriptEngine *)
+{
+ static int x = 0;
+ return QScriptValue(x++);
+}
+
+void tst_script::property_getter()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.newObject();
+ v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_method),
+ QScriptValue::PropertyGetter);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+static TestObject *property_getter_qobject_object = 0;
+static QScriptValue property_getter_qobject_method(QScriptContext *, QScriptEngine *)
+{
+ static int idx = -1;
+ if (idx == -1)
+ idx = TestObject::staticMetaObject.indexOfProperty("x");
+
+ int value = 0;
+ void *args[] = { &value, 0 };
+ QMetaObject::metacall(property_getter_qobject_object, QMetaObject::ReadProperty, idx, args);
+
+ return QScriptValue(value);
+}
+
+static QScriptValue property_getter_qmetaproperty_method(QScriptContext *, QScriptEngine *)
+{
+ static int idx = -1;
+ if (idx == -1)
+ idx = TestObject::staticMetaObject.indexOfProperty("x");
+
+ int value = 0;
+ value = property_getter_qobject_object->metaObject()->property(idx).read(property_getter_qobject_object).toInt();
+
+ return QScriptValue(value);
+}
+
+void tst_script::property_getter_qobject()
+{
+ QScriptEngine engine;
+
+ TestObject to;
+ property_getter_qobject_object = &to;
+ QScriptValue v = engine.newObject();
+ v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qobject_method),
+ QScriptValue::PropertyGetter);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+ property_getter_qobject_object = 0;
+}
+
+void tst_script::property_getter_qmetaproperty()
+{
+ QScriptEngine engine;
+
+ TestObject to;
+ property_getter_qobject_object = &to;
+ QScriptValue v = engine.newObject();
+ v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qmetaproperty_method),
+ QScriptValue::PropertyGetter);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+ property_getter_qobject_object = 0;
+}
+
+
+void tst_script::property_getter_js()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.__defineGetter__(\"x\", function() { return this._x++; }); return o; })").call();
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+void tst_script::property_qobject()
+{
+ QScriptEngine engine;
+
+ TestObject to;
+ QScriptValue v = engine.newQObject(&to);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+void tst_script::property_qmlobject()
+{
+ QmlEngine qmlengine;
+
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(&qmlengine);
+ TestObject to;
+
+ QScriptValue v = QmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine->evaluate(PROPERTY_PROGRAM).call(engine->globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+#define FUNCTION_PROGRAM \
+ "(function(testObject) { return (function() { " \
+ " var test = 0; " \
+ " for (var ii = 0; ii < 10000; ++ii) { " \
+ " test += testObject.method(); " \
+ " } " \
+ " return test; " \
+ "}); })"
+
+void tst_script::function_js()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.method = (function() { return this._x++; }); return o; })").call();
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+static QScriptValue function_method(QScriptContext *, QScriptEngine *)
+{
+ static int x = 0;
+ return QScriptValue(x++);
+}
+
+void tst_script::function_cpp()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.newObject();
+ v.setProperty(QLatin1String("method"), engine.newFunction(function_method));
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+void tst_script::function_qobject()
+{
+ QScriptEngine engine;
+
+ TestObject to;
+ QScriptValue v = engine.newQObject(&to);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+void tst_script::function_qmlobject()
+{
+ QmlEngine qmlengine;
+
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(&qmlengine);
+ TestObject to;
+
+ QScriptValue v = QmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine->evaluate(FUNCTION_PROGRAM).call(engine->globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+#define FUNCTION_ARGS_PROGRAM \
+ "(function(testObject) { return (function() { " \
+ " var test = 0; " \
+ " for (var ii = 0; ii < 10000; ++ii) { " \
+ " test += testObject.methodArgs(ii); " \
+ " } " \
+ " return test; " \
+ "}); })"
+
+void tst_script::function_args_js()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.methodArgs = (function(a) { return a + this._x++; }); return o; })").call();
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+static QScriptValue function_args_method(QScriptContext *ctxt, QScriptEngine *)
+{
+ static int x = 0;
+ return QScriptValue(ctxt->argument(0).toNumber() + x++);
+}
+
+void tst_script::function_args_cpp()
+{
+ QScriptEngine engine;
+
+ QScriptValue v = engine.newObject();
+ v.setProperty(QLatin1String("methodArgs"), engine.newFunction(function_args_method));
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+void tst_script::function_args_qobject()
+{
+ QScriptEngine engine;
+
+ TestObject to;
+ QScriptValue v = engine.newQObject(&to);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+void tst_script::function_args_qmlobject()
+{
+ QmlEngine qmlengine;
+
+ QScriptEngine *engine = QmlEnginePrivate::getScriptEngine(&qmlengine);
+ TestObject to;
+
+ QScriptValue v = QmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
+
+ QScriptValueList args;
+ args << v;
+ QScriptValue prog = engine->evaluate(FUNCTION_ARGS_PROGRAM).call(engine->globalObject(), args);
+ prog.call();
+
+ QBENCHMARK {
+ prog.call();
+ }
+}
+
+QTEST_MAIN(tst_script)
+
+#include "tst_script.moc"