summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-12-02 02:35:38 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-12-02 02:35:38 (GMT)
commitcb70f2096cbc66e6e8b5324e0e9508c788144e7e (patch)
treedd4f6f98e2b27d09f2b7c275e705b5a28e89d541
parentec42d6843ca0937f338e5e2d7d3353134d143eb6 (diff)
downloadQt-cb70f2096cbc66e6e8b5324e0e9508c788144e7e.zip
Qt-cb70f2096cbc66e6e8b5324e0e9508c788144e7e.tar.gz
Qt-cb70f2096cbc66e6e8b5324e0e9508c788144e7e.tar.bz2
Cache binding closures
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp1
-rw-r--r--src/declarative/qml/qmlcompiler.cpp9
-rw-r--r--src/declarative/qml/qmlcompiler_p.h1
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp33
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h1
-rw-r--r--src/declarative/qml/qmlengine.cpp2
-rw-r--r--src/declarative/qml/qmlengine_p.h2
-rw-r--r--src/declarative/qml/qmlexpression.cpp56
-rw-r--r--src/declarative/qml/qmlexpression_p.h2
-rw-r--r--src/declarative/qml/qmlrewrite.cpp16
-rw-r--r--src/declarative/qml/qmlrewrite_p.h11
11 files changed, 118 insertions, 16 deletions
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp
index 44d2745..3428574 100644
--- a/src/declarative/qml/qmlcompileddata.cpp
+++ b/src/declarative/qml/qmlcompileddata.cpp
@@ -168,6 +168,7 @@ QmlCompiledData::~QmlCompiledData()
importCache->release();
qDeleteAll(programs);
+ qDeleteAll(cachedValues);
}
QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt, const QBitField &bindings) const
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index a4e14b2..a0e9418 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -2529,12 +2529,21 @@ bool QmlCompiler::completeComponentBuild()
// Pre-rewrite the expression
QString expression = binding.expression.asScript();
+
+ // ### Optimize
+ QmlRewrite::SharedBindingTester sharableTest;
+ bool isSharable = sharableTest.isSharable(expression);
+
QmlRewrite::RewriteBinding rewriteBinding;
expression = rewriteBinding(expression);
quint32 length = expression.length();
quint32 pc = output->programs.length();
+ if (isSharable)
+ pc |= 0x80000000;
+
output->programs.append(0);
+ output->cachedValues.append(0);
binding.compiledData =
QByteArray((const char *)&pc, sizeof(quint32)) +
QByteArray((const char *)&length, sizeof(quint32)) +
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index b54a62a..ca26062 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -114,6 +114,7 @@ public:
QList<QmlParser::Location> locations;
QList<QmlInstruction> bytecode;
QList<QScriptProgram *> programs;
+ QList<QScriptValue *> cachedValues;
QList<QmlPropertyCache *> propertyCaches;
QList<QmlIntegerCache *> contextCaches;
QList<QmlParser::Object::ScriptBlock> scripts;
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
index fda284a..a95400a 100644
--- a/src/declarative/qml/qmlcontextscriptclass.cpp
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -47,9 +47,27 @@
QT_BEGIN_NAMESPACE
struct ContextData : public QScriptDeclarativeClass::Object {
- ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {}
+ ContextData() : isSharedContext(true) {}
+ ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o), isSharedContext(false) {}
QGuard<QmlContext> context;
QGuard<QObject> scopeObject;
+ bool isSharedContext;
+
+ QmlContext *getContext(QmlEngine *engine) {
+ if (isSharedContext) {
+ return QmlEnginePrivate::get(engine)->sharedContext;
+ } else {
+ return context.data();
+ }
+ }
+
+ QObject *getScope(QmlEngine *engine) {
+ if (isSharedContext) {
+ return QmlEnginePrivate::get(engine)->sharedScope;
+ } else {
+ return scopeObject.data();
+ }
+ }
};
/*
@@ -73,13 +91,20 @@ QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *sco
return newObject(scriptEngine, this, new ContextData(context, scopeObject));
}
+QScriptValue QmlContextScriptClass::newSharedContext()
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new ContextData());
+}
+
QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
{
if (scriptClass(v) != this)
return 0;
ContextData *data = (ContextData *)object(v);
- return data->context;
+ return data->getContext(engine);
}
QScriptClass::QueryFlags
@@ -94,8 +119,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
lastPropertyIndex = -1;
lastDefaultObject = -1;
- QmlContext *bindContext = ((ContextData *)object)->context.data();
- QObject *scopeObject = ((ContextData *)object)->scopeObject.data();
+ QmlContext *bindContext = ((ContextData *)object)->getContext(engine);
+ QObject *scopeObject = ((ContextData *)object)->getScope(engine);
if (!bindContext)
return 0;
diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h
index bbd779b..10b848a 100644
--- a/src/declarative/qml/qmlcontextscriptclass_p.h
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -68,6 +68,7 @@ public:
~QmlContextScriptClass();
QScriptValue newContext(QmlContext *, QObject * = 0);
+ QScriptValue newSharedContext();
QmlContext *contextFromValue(const QScriptValue &);
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 9afb81e..0e24fd2 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -110,7 +110,7 @@ struct StaticQtMetaObject : public QObject
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentExpression(0),
- isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), globalClass(0),
+ isDebugging(false), contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0), globalClass(0),
nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), cleanup(0), erroredBindings(0),
inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttacheds(0),
rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 9e0c1fc..4eb9843 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -126,6 +126,8 @@ public:
struct ImportedNamespace;
QmlContextScriptClass *contextClass;
+ QmlContext *sharedContext;
+ QObject *sharedScope;
QmlObjectScriptClass *objectClass;
QmlValueTypeScriptClass *valueTypeClass;
QmlTypeNameScriptClass *typeNameClass;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index d2d60ee..703fcf5 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
QmlExpressionData::QmlExpressionData()
: expressionFunctionValid(false), expressionRewritten(false), me(0),
- trackChange(true), line(-1), guardList(0), guardListLength(0)
+ trackChange(true), isShared(false), line(-1), guardList(0), guardListLength(0)
{
}
@@ -108,27 +108,47 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]);
int progIdx = *(exprData + 1);
+ bool isShared = progIdx & 0x80000000;
+ progIdx &= 0x7FFFFFFF;
+
QmlEngine *engine = ctxt->engine();
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (isShared) {
+
+ if (!dd->cachedValues.at(progIdx)) {
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newSharedContext());
+ dd->cachedValues[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url.toString(), data->line));
+ scriptEngine->popContext();
+ }
+
+ data->expressionFunction = *dd->cachedValues.at(progIdx);
+ data->isShared = true;
+ data->expressionFunctionValid = true;
+
+ } else {
+
#if !defined(Q_OS_SYMBIAN) //XXX Why doesn't this work?
- if (!dd->programs.at(progIdx)) {
- dd->programs[progIdx] =
- new QScriptProgram(data->expression, data->url.toString(), data->line);
- }
+ if (!dd->programs.at(progIdx)) {
+ dd->programs[progIdx] =
+ new QScriptProgram(data->expression, data->url.toString(), data->line);
+ }
#endif
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- scriptContext->pushScope(ep->contextClass->newContext(ctxt, me));
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newContext(ctxt, me));
#if !defined(Q_OS_SYMBIAN)
- data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
+ data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
#else
- data->expressionFunction = scriptEngine->evaluate(data->expression);
+ data->expressionFunction = scriptEngine->evaluate(data->expression);
#endif
- data->expressionFunctionValid = true;
- scriptEngine->popContext();
+ data->expressionFunctionValid = true;
+ scriptEngine->popContext();
+ }
}
data->QmlAbstractExpression::setContext(ctxt);
@@ -328,8 +348,22 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUnd
data->expressionFunctionValid = true;
}
+ QmlContext *oldSharedContext = 0;
+ QObject *oldSharedScope = 0;
+ if (data->isShared) {
+ oldSharedContext = ep->sharedContext;
+ oldSharedScope = ep->sharedScope;
+ ep->sharedContext = data->context();
+ ep->sharedScope = data->me;
+ }
+
QScriptValue svalue = data->expressionFunction.call();
+ if (data->isShared) {
+ ep->sharedContext = oldSharedContext;
+ ep->sharedScope = oldSharedScope;
+ }
+
if (isUndefined)
*isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index c6ba54d..dbb12ba 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -101,6 +101,8 @@ public:
QObject *me;
bool trackChange;
+ bool isShared;
+
QUrl url;
int line;
diff --git a/src/declarative/qml/qmlrewrite.cpp b/src/declarative/qml/qmlrewrite.cpp
index 32e2fef..2964a75 100644
--- a/src/declarative/qml/qmlrewrite.cpp
+++ b/src/declarative/qml/qmlrewrite.cpp
@@ -49,6 +49,22 @@ DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
namespace QmlRewrite {
+bool SharedBindingTester::isSharable(const QString &code)
+{
+ Engine engine;
+ NodePool pool(QString(), &engine);
+ Lexer lexer(&engine);
+ Parser parser(&engine);
+ lexer.setCode(code, 0);
+ parser.parseStatement();
+ if (!parser.statement())
+ return false;
+
+ _sharable = true;
+ AST::Node::acceptChild(parser.statement(), this);
+ return _sharable;
+}
+
QString RewriteBinding::operator()(const QString &code, bool *ok)
{
Engine engine;
diff --git a/src/declarative/qml/qmlrewrite_p.h b/src/declarative/qml/qmlrewrite_p.h
index a5cb841..a04a0db 100644
--- a/src/declarative/qml/qmlrewrite_p.h
+++ b/src/declarative/qml/qmlrewrite_p.h
@@ -63,6 +63,17 @@ QT_BEGIN_NAMESPACE
namespace QmlRewrite {
using namespace QmlJS;
+class SharedBindingTester : protected AST::Visitor
+{
+ bool _sharable;
+public:
+ bool isSharable(const QString &code);
+
+ virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; }
+ virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; }
+ virtual bool visit(AST::CallExpression *) { _sharable = false; return false; }
+};
+
class RewriteBinding: protected AST::Visitor
{
unsigned _position;