aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-10-09 00:24:55 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-11 22:55:02 +0200
commit774963f52f569e637f45d6c6079121253e54b61b (patch)
treeb007dcdbe49a90db727593d4e1966c92d4622dee /src/qml/qml
parentc39393e7de5b808adbc9c5771ecca161c9660d7c (diff)
Compile JS functions as part of the QQmlCompiler run in the loader thread
...instead of extracting the function body as a string and compiling it in the GUI thread. Change-Id: I3c3108f6e35464b5581a2d8b5799e7285858ce4d Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlcompiler.cpp35
-rw-r--r--src/qml/qml/qqmlcompiler_p.h7
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp5
-rw-r--r--src/qml/qml/qqmlscript.cpp5
-rw-r--r--src/qml/qml/qqmlscript_p.h4
-rw-r--r--src/qml/qml/qqmlvme.cpp3
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp30
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h6
8 files changed, 50 insertions, 45 deletions
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index afbec31cb5..d14c790aad 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -811,6 +811,7 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
this->unitRoot = root;
this->output = out;
this->functionsToCompile.clear();
+ this->compiledMetaMethods.clear();
// Compile types
const QList<QQmlTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
@@ -955,6 +956,13 @@ void QQmlCompiler::compileTree(QQmlScript::Object *tree)
}
}
+ foreach (const CompiledMetaMethod &cmm, compiledMetaMethods) {
+ typedef QQmlVMEMetaData VMD;
+ VMD *vmd = (QQmlVMEMetaData *)cmm.obj->synthdata.data();
+ VMD::MethodData &md = *(vmd->methodData() + cmm.methodIndex);
+ md.runtimeFunctionIndex = runtimeFunctionIndices.at(cmm.compiledFunctionIndex);
+ }
+
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Compiler::JSUnitGenerator jsUnitGenerator(&jsModule);
QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(v4->executableAllocator, &jsModule, &jsUnitGenerator));
@@ -3234,24 +3242,8 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
// Dynamic slot data - comes after the property data
for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- int paramCount = s->parameterNames.count();
-
- QString funcScript;
- int namesSize = 0;
- if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
- funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ +
- namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
- funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
- for (int jj = 0; jj < paramCount; ++jj) {
- if (jj) funcScript.append(QLatin1Char(','));
- funcScript.append(QLatin1String(s->parameterNames.at(jj)));
- }
- funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
-
- QByteArray utf8 = funcScript.toUtf8();
- VMD::MethodData methodData = { s->parameterNames.count(),
- dynamicData.size(),
- utf8.length(),
+ VMD::MethodData methodData = { /*runtimeFunctionIndex*/ 0, // To be filled in later
+ s->parameterNames.count(),
s->location.start.line };
VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
@@ -3259,7 +3251,12 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
vmd->methodCount++;
md = methodData;
- dynamicData.append((const char *)utf8.constData(), utf8.length());
+ CompiledMetaMethod cmm;
+ cmm.obj = obj;
+ cmm.methodIndex = vmd->methodCount - 1;
+ functionsToCompile.append(s->funcDecl);
+ cmm.compiledFunctionIndex = functionsToCompile.count() - 1;
+ compiledMetaMethods.append(cmm);
}
if (aliasCount)
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 9ad0b7f0f9..1d1306fba4 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -463,6 +463,13 @@ private:
QList<QQmlJS::AST::Node*> functionsToCompile;
QList<QQmlCompilerTypes::JSBindingReference*> allBindingReferenceRoots;
+ struct CompiledMetaMethod
+ {
+ QQmlScript::Object *obj;
+ int methodIndex;
+ int compiledFunctionIndex; // index in functionToCompile
+ };
+ QList<CompiledMetaMethod> compiledMetaMethods;
// Compiler component statistics. Only collected if QML_COMPILER_STATS=1
struct ComponentStat
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 42ec886bae..4e70e14894 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -445,9 +445,8 @@ bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQml
for (quint32 i = 0; i < obj->nFunctions; ++i, ++functionIndex) {
const QV4::CompiledData::Function *s = qmlUnit->header.functionAt(*functionIndex);
- VMD::MethodData methodData = { int(s->nFormals),
- /* body offset*/0,
- /* body length*/0,
+ VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
+ int(s->nFormals),
/* s->location.start.line */0 }; // ###
VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index 88603ac2a8..4c1a1f7be5 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -202,7 +202,7 @@ QQmlScript::Object::DynamicSignal::DynamicSignal()
}
QQmlScript::Object::DynamicSlot::DynamicSlot()
-: nextSlot(0), nameIndex(-1)
+: funcDecl(0), nextSlot(0), nameIndex(-1)
{
}
@@ -1284,9 +1284,8 @@ bool ProcessAST::visit(AST::UiSourceElement *node)
AST::SourceLocation loc = funDecl->rparenToken;
loc.offset = loc.end();
loc.startColumn += 1;
- QString body = textAt(loc, funDecl->rbraceToken);
slot->name = funDecl->name;
- slot->body = body;
+ slot->funcDecl = funDecl;
obj->dynamicSlots.append(slot);
} else {
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index f8786b0a2d..7aecba993b 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
class QByteArray;
class QQmlPropertyCache;
-namespace QQmlJS { class Engine; namespace AST { class Node; class StringLiteral; class UiProgram; } }
+namespace QQmlJS { class Engine; namespace AST { class Node; class StringLiteral; class UiProgram; class FunctionDeclaration; } }
namespace QQmlCompilerTypes { struct BindingReference; struct ComponentCompileState; }
namespace QQmlScript {
@@ -433,8 +433,8 @@ public:
{
DynamicSlot();
+ QQmlJS::AST::FunctionDeclaration *funcDecl;
QHashedStringRef name;
- QString body;
QList<QByteArray> parameterNames;
LocationSpan location;
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index c5dfeb2956..21f7ce4cab 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -714,7 +714,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
const QQmlVMEMetaData *data =
(const QQmlVMEMetaData *)DATAS.at(instr.aliasData).constData();
- (void)new QQmlVMEMetaObject(target, propertyCache, data);
+ QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, target, objects.count() - 1);
+ (void)new QQmlVMEMetaObject(target, propertyCache, data, qmlContext, COMP);
QQmlData *ddata = QQmlData::get(target, true);
if (ddata->propertyCache) ddata->propertyCache->release();
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 7c033acf47..915314e322 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -559,7 +559,7 @@ QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
QQmlPropertyCache *cache,
- const QQmlVMEMetaData *meta)
+ const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
: object(obj),
ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1),
@@ -603,6 +603,21 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
if (needsJSWrapper)
ensureQObjectWrapper();
+
+ if (qmlBindingContext && metaData->methodCount) {
+ v8methods = new QV4::PersistentValue[metaData->methodCount];
+
+ QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit;
+ QV4::Scope scope(QQmlEnginePrivate::get(ctxt->engine)->v4engine());
+ QV4::ScopedObject o(scope);
+ for (int index = 0; index < metaData->methodCount; ++index) {
+ QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
+
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
+ o = QV4::FunctionObject::creatScriptFunction(qmlBindingContext, runtimeFunction);
+ v8methods[index] = o;
+ }
+ }
}
QQmlVMEMetaObject::~QQmlVMEMetaObject()
@@ -974,19 +989,6 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
if (!v8methods)
v8methods = new QV4::PersistentValue[metaData->methodCount];
- if (v8methods[index].isUndefined()) {
- QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
-
- const char *body = ((const char*)metaData) + data->bodyOffset;
- int bodyLength = data->bodyLength;
-
- // 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
- v8methods[index] = QQmlExpressionPrivate::evalFunction(ctxt, object, QString::fromUtf8(body, bodyLength),
- ctxt->urlString, data->lineNumber);
- }
-
return v8methods[index].value();
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 056139114c..25a577d2e6 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -119,9 +119,8 @@ struct QQmlVMEMetaData
};
struct MethodData {
+ int runtimeFunctionIndex;
int parameterCount;
- int bodyOffset;
- int bodyLength;
quint16 lineNumber;
};
@@ -159,7 +158,8 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QAbstractDynamicMetaObject
{
public:
- QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
+ QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data,
+ QV4::ExecutionContext *qmlBindingContext = 0, QQmlCompiledData *compiledData = 0);
~QQmlVMEMetaObject();
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;