summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-06-10 04:16:19 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-06-10 04:16:19 (GMT)
commitb14a89473a51bee7cc2f313b88a8bc1e87a454d8 (patch)
treeed19f68437ab3d63570b7dc374357f898811d72a /src/declarative
parent1ef0d84c8e5d706e60e487fc801f90bbf5fddaa6 (diff)
downloadQt-b14a89473a51bee7cc2f313b88a8bc1e87a454d8.zip
Qt-b14a89473a51bee7cc2f313b88a8bc1e87a454d8.tar.gz
Qt-b14a89473a51bee7cc2f313b88a8bc1e87a454d8.tar.bz2
Improve bindings startup performance
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qml.pri3
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp166
-rw-r--r--src/declarative/qml/qmlbasicscript_p.h11
-rw-r--r--src/declarative/qml/qmlcompiler.cpp55
-rw-r--r--src/declarative/qml/qmlcompiler_p.h44
-rw-r--r--src/declarative/qml/qmlengine.cpp28
-rw-r--r--src/declarative/qml/qmlengine_p.h12
-rw-r--r--src/declarative/qml/qmlexpression.h2
-rw-r--r--src/declarative/qml/qmlvme.cpp4
-rw-r--r--src/declarative/qml/qpodvector_p.h124
10 files changed, 356 insertions, 93 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index c61200e..efe4d3f 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -63,7 +63,8 @@ HEADERS += qml/qmlparser_p.h \
qml/qmldeclarativedata_p.h \
qml/qmlerror.h \
qml/qmlscriptparser_p.h \
- qml/qmlbasicscript_p.h
+ qml/qmlbasicscript_p.h \
+ qml/qpodvector_p.h
# for qtscript debugger
QT += scripttools
diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
index 7bd898c..d8e65bf 100644
--- a/src/declarative/qml/qmlbasicscript.cpp
+++ b/src/declarative/qml/qmlbasicscript.cpp
@@ -22,11 +22,19 @@
QT_BEGIN_NAMESPACE
+using namespace JavaScript;
+
struct ScriptInstruction {
enum {
Load, // fetch
Fetch, // fetch
+ LoadIdObject, // fetch
+ FetchConstant, // constant
+ FetchD0Constant, // constant
+ FetchD1Constant, // constant
+
+
Add, // NA
Subtract, // NA
Multiply, // NA
@@ -47,6 +55,11 @@ struct ScriptInstruction {
struct {
bool value;
} boolean;
+ struct {
+ short idx;
+ short notify;
+ int type;
+ } constant;
};
};
@@ -249,9 +262,14 @@ struct QmlBasicScriptCompiler
{
QmlBasicScriptCompiler()
: script(0), stateSize(0) {}
+
QmlBasicScript *script;
int stateSize;
+ QmlParser::Object *context;
+ QmlParser::Object *component;
+ QHash<QString, QPair<QmlParser::Object *, int> > ids;
+
bool compile(JavaScript::AST::Node *);
bool compileExpression(JavaScript::AST::Node *);
@@ -259,7 +277,7 @@ struct QmlBasicScriptCompiler
bool tryConstant(JavaScript::AST::Node *);
bool parseConstant(JavaScript::AST::Node *);
bool tryName(JavaScript::AST::Node *);
- bool parseName(JavaScript::AST::Node *);
+ bool parseName(JavaScript::AST::Node *, QmlParser::Object ** = 0);
bool tryBinaryExpression(JavaScript::AST::Node *);
bool compileBinaryExpression(JavaScript::AST::Node *);
@@ -437,19 +455,18 @@ bool QmlBasicScript::isValid() const
return d != 0;
}
-/*!
- Compile \a v and return true if the compilation is successful, otherwise
- returns false.
- */
-bool QmlBasicScript::compile(const QmlParser::Variant &v)
+bool QmlBasicScript::compile(const Expression &expression)
{
- if (!v.asAST()) return false;
+ if (!expression.expression.asAST()) return false;
- QByteArray expr = v.asScript().toLatin1();
+ QByteArray expr = expression.expression.asScript().toLatin1();
const char *src = expr.constData();
QmlBasicScriptCompiler bsc;
bsc.script = this;
+ bsc.context = expression.context;
+ bsc.component = expression.component;
+ bsc.ids = expression.ids;
if (d) {
if (flags & QmlBasicScriptPrivate::OwnData)
@@ -458,7 +475,7 @@ bool QmlBasicScript::compile(const QmlParser::Variant &v)
flags = 0;
}
- if (bsc.compile(v.asAST())) {
+ if (bsc.compile(expression.expression.asAST())) {
int len = ::strlen(src);
flags = QmlBasicScriptPrivate::OwnData;
int size = sizeof(QmlBasicScriptPrivate) +
@@ -483,7 +500,6 @@ bool QmlBasicScriptCompiler::compile(JavaScript::AST::Node *node)
return compileExpression(node);
}
-using namespace JavaScript;
bool QmlBasicScriptCompiler::tryConstant(JavaScript::AST::Node *node)
{
if (node->kind == AST::Node::Kind_TrueLiteral ||
@@ -524,10 +540,11 @@ bool QmlBasicScriptCompiler::tryName(JavaScript::AST::Node *node)
node->kind == AST::Node::Kind_FieldMemberExpression;
}
-bool QmlBasicScriptCompiler::parseName(AST::Node *node)
+bool QmlBasicScriptCompiler::parseName(AST::Node *node,
+ QmlParser::Object **type)
{
bool load = false;
-
+ QmlParser::Object *loadedType = 0;
QString name;
if (node->kind == AST::Node::Kind_IdentifierExpression) {
name = static_cast<AST::IdentifierExpression *>(node)->name->asString();
@@ -535,7 +552,7 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node)
} else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
AST::FieldMemberExpression *expr = static_cast<AST::FieldMemberExpression *>(node);
- if (!parseName(expr->base))
+ if (!parseName(expr->base, &loadedType))
return false;
name = expr->name->asString();
@@ -543,18 +560,72 @@ bool QmlBasicScriptCompiler::parseName(AST::Node *node)
return false;
}
- int nref = data.count();
- data.append(name.toUtf8());
- data.append('\0');
ScriptInstruction instr;
- if (load)
- instr.type = ScriptInstruction::Load;
- else
- instr.type = ScriptInstruction::Fetch;
- instr.fetch.idx = nref;
- bytecode.append(instr);
- ++stateSize;
+ if (load) {
+ if (ids.contains(name)) {
+ instr.type = ScriptInstruction::LoadIdObject;
+ instr.fetch.idx = ids.value(name).second;
+
+ if (type)
+ *type = ids.value(name).first;
+
+ } else {
+ int d0Idx = context->metaObject()->indexOfProperty(name.toUtf8().constData());
+ int d1Idx = -1;
+ if (d0Idx == -1)
+ d1Idx = component->metaObject()->indexOfProperty(name.toUtf8().constData());
+ if (d0Idx != -1) {
+
+ instr.type = ScriptInstruction::FetchD0Constant;
+ instr.constant.idx = d0Idx;
+ QMetaProperty prop = context->metaObject()->property(d0Idx);
+ instr.constant.notify = prop.notifySignalIndex();
+ instr.constant.type = prop.userType();
+
+ } else if (d1Idx != -1) {
+
+ instr.type = ScriptInstruction::FetchD1Constant;
+ instr.constant.idx = d1Idx;
+ QMetaProperty prop = component->metaObject()->property(d1Idx);
+ instr.constant.notify = prop.notifySignalIndex();
+ instr.constant.type = prop.userType();
+
+ } else {
+
+ int nref = data.count();
+ data.append(name.toUtf8());
+ data.append('\0');
+ instr.type = ScriptInstruction::Load;
+ instr.fetch.idx = nref;
+ ++stateSize;
+
+ }
+ }
+
+ } else {
+
+ int idx = -1;
+ if (loadedType)
+ idx = loadedType->metaObject()->indexOfProperty(name.toUtf8().constData());
+ if (idx != -1) {
+ instr.type = ScriptInstruction::FetchConstant;
+ instr.constant.idx = idx;
+ QMetaProperty prop = loadedType->metaObject()->property(idx);
+ instr.constant.notify = prop.notifySignalIndex();
+ instr.constant.type = prop.userType();
+ } else {
+ int nref = data.count();
+ data.append(name.toUtf8());
+ data.append('\0');
+ instr.type = ScriptInstruction::Fetch;
+ instr.fetch.idx = nref;
+ ++stateSize;
+ }
+
+ }
+
+ bytecode.append(instr);
return true;
}
@@ -679,12 +750,16 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
{
if (!isValid())
return QVariant();
+
+ QmlContextPrivate *contextPrivate = context->d_func();
+ QmlEnginePrivate *enginePrivate = context->engine()->d_func();
QmlBasicScriptNodeCache *dataCache =
reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
int dataCacheItem;
- QStack<QVariant> stack;
+ QStack<QVariant> stack;
+
bool resetting = false;
bool hasReset = false;
@@ -702,6 +777,49 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
const ScriptInstruction &instr = d->instructions()[idx];
switch(instr.type) {
+ case ScriptInstruction::LoadIdObject:
+ {
+ stack.push(contextPrivate->propertyValues.at(instr.fetch.idx));
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(context, contextPrivate->notifyIndex + instr.fetch.idx);
+ state = Reset;
+ }
+ break;
+
+ case ScriptInstruction::FetchD0Constant:
+ {
+ QObject *obj = contextPrivate->defaultObjects.at(0);
+
+ stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, instr.constant.notify);
+ state = Reset;
+ }
+ break;
+
+ case ScriptInstruction::FetchD1Constant:
+ {
+ QObject *obj = contextPrivate->defaultObjects.at(1);
+
+ stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, instr.constant.notify);
+ state = Reset;
+ }
+ break;
+
+ case ScriptInstruction::FetchConstant:
+ {
+ QVariant o = stack.pop();
+ QObject *obj = qvariant_cast<QObject *>(o);
+
+ stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, instr.constant.notify);
+ state = Reset;
+ }
+ break;
+
case ScriptInstruction::Load: // either an object or a property
case ScriptInstruction::Fetch: // can only be a property
{
diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h
index 1117e11..43c0d36 100644
--- a/src/declarative/qml/qmlbasicscript_p.h
+++ b/src/declarative/qml/qmlbasicscript_p.h
@@ -38,7 +38,16 @@ public:
QByteArray expression() const;
- bool compile(const QmlParser::Variant &);
+ struct Expression
+ {
+ QmlParser::Object *component;
+ QmlParser::Object *context;
+ QmlParser::Property *property;
+ QmlParser::Variant expression;
+ QHash<QString, QPair<QmlParser::Object *, int> > ids;
+ };
+
+ bool compile(const Expression &);
bool isValid() const;
void clear();
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index b28d7dd..fe3da57 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -533,6 +533,8 @@ bool QmlCompiler::compile(QmlEngine *engine,
void QmlCompiler::compileTree(Object *tree)
{
+ compileState.root = tree;
+
QmlInstruction init;
init.type = QmlInstruction::Init;
init.line = 0;
@@ -557,7 +559,7 @@ void QmlCompiler::compileTree(Object *tree)
finalizeComponent(0);
}
-bool QmlCompiler::compileObject(Object *obj, int ctxt)
+bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt)
{
Q_ASSERT (obj->type != -1);
obj->metatype = output->types.at(obj->type).metaObject();
@@ -567,7 +569,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
return true;
}
- ctxt = 0;
+ BindingContext objCtxt(obj);
int createInstrIdx = output->bytecode.count();
// Create the object
@@ -617,7 +619,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
if (isCustomParser) {
// Custom parser types don't support signal properties
if (testProperty(prop, obj)) {
- COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
} else {
customProps << QmlCustomParserNodePrivate::fromProperty(prop);
}
@@ -625,7 +627,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
if (isSignalPropertyName(prop->name)) {
COMPILE_CHECK(compileSignal(prop,obj));
} else {
- COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
}
}
@@ -637,12 +639,12 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
if (isCustomParser) {
if (testProperty(prop, obj)) {
- COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
} else {
customProps << QmlCustomParserNodePrivate::fromProperty(prop);
}
} else {
- COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ COMPILE_CHECK(compileProperty(prop, obj, objCtxt));
}
}
@@ -673,7 +675,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt)
return true;
}
-bool QmlCompiler::compileComponent(Object *obj, int ctxt)
+bool QmlCompiler::compileComponent(Object *obj, const BindingContext &ctxt)
{
Property *idProp = 0;
if (obj->properties.count() > 1 ||
@@ -709,6 +711,7 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt)
reference.id = val;
reference.object = obj;
reference.instructionIdx = output->bytecode.count();
+ reference.idx = compileState.ids.count();
compileState.ids.insert(val, reference);
int pref = output->indexForString(val);
@@ -724,7 +727,7 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt)
return true;
}
-bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
+bool QmlCompiler::compileComponentFromRoot(Object *obj, const BindingContext &ctxt)
{
output->bytecode.push_back(QmlInstruction());
QmlInstruction &create = output->bytecode.last();
@@ -743,6 +746,7 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
ComponentCompileState oldComponentCompileState = compileState;
compileState = ComponentCompileState();
+ compileState.root = obj;
if (obj)
COMPILE_CHECK(compileObject(obj, ctxt));
@@ -753,7 +757,7 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
}
-bool QmlCompiler::compileFetchedObject(Object *obj, int ctxt)
+bool QmlCompiler::compileFetchedObject(Object *obj, const BindingContext &ctxt)
{
Q_ASSERT(obj->metatype);
@@ -871,7 +875,7 @@ bool QmlCompiler::testProperty(QmlParser::Property *prop,
return false;
}
-bool QmlCompiler::compileProperty(Property *prop, Object *obj, int ctxt)
+bool QmlCompiler::compileProperty(Property *prop, Object *obj, const BindingContext &ctxt)
{
if (prop->values.isEmpty() && !prop->value)
COMPILE_EXCEPTION2(prop, "Empty property assignment");
@@ -992,6 +996,7 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
reference.id = val;
reference.object = obj;
reference.instructionIdx = output->bytecode.count();
+ reference.idx = compileState.ids.count();
compileState.ids.insert(val, reference);
QmlInstruction id;
@@ -1012,7 +1017,7 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
// }
// GridView is an attached property object.
bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
- int ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->value);
int id = QmlMetaType::attachedPropertiesFuncId(prop->name);
@@ -1024,7 +1029,7 @@ bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
fetch.fetchAttached.id = id;
output->bytecode << fetch;
- COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt.incr()));
QmlInstruction pop;
pop.type = QmlInstruction::PopFetchedObject;
@@ -1040,7 +1045,7 @@ bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
// }
// font is a nested property. size is not.
bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
- int ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->type != 0);
Q_ASSERT(prop->index != -1);
@@ -1057,7 +1062,7 @@ bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
fetch.line = prop->location.start.line;
output->bytecode << fetch;
- COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt.incr()));
QmlInstruction pop;
pop.type = QmlInstruction::PopFetchedObject;
@@ -1074,7 +1079,7 @@ bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
// QmlList<T *> * types can accept a list of objects
bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
QmlParser::Object *obj,
- int ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(QmlMetaType::isList(prop->type) ||
QmlMetaType::isQmlList(prop->type));
@@ -1166,7 +1171,7 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
// We allow assignming multiple values to single value properties
bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
QmlParser::Object *obj,
- int ctxt)
+ const BindingContext &ctxt)
{
for (int ii = 0; ii < prop->values.count(); ++ii) {
Value *v = prop->values.at(ii);
@@ -1187,7 +1192,7 @@ bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
// Compile assigning a single object instance to a regular property
bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
QmlParser::Value *v,
- int ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(v->object->type != -1);
@@ -1296,7 +1301,7 @@ bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
QmlParser::Object *obj,
QmlParser::Value *v,
- int ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
@@ -1409,7 +1414,7 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj)
bool QmlCompiler::compileBinding(QmlParser::Value *value,
QmlParser::Property *prop,
- int ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index);
Q_ASSERT(prop->parent);
@@ -1491,7 +1496,15 @@ void QmlCompiler::finalizeComponent(int patch)
void QmlCompiler::finalizeBinding(const BindingReference &binding)
{
QmlBasicScript bs;
- bs.compile(binding.expression);
+ QmlBasicScript::Expression expr;
+ expr.component = compileState.root;
+ expr.context = binding.bindingContext.object;
+ expr.property = binding.property;
+ expr.expression = binding.expression;
+ foreach (const IdReference &id, compileState.ids)
+ expr.ids.insert(id.id, qMakePair(id.object, id.idx));
+
+ bs.compile(expr);
QmlInstruction &instr = output->bytecode[binding.instructionIdx];
instr.line = binding.value->location.start.line;
@@ -1553,7 +1566,7 @@ void QmlCompiler::finalizeBinding(const BindingReference &binding)
bref = output->indexForString(binding.expression.asScript());
}
- instr.assignBinding.context = binding.bindingContext;
+ instr.assignBinding.context = binding.bindingContext.stack;
if (bs.isValid())
instr.type = QmlInstruction::StoreCompiledBinding;
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 6b6e1e2..6b6d8cb 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -125,41 +125,55 @@ public:
private:
void reset(QmlCompiledComponent *, bool);
+ struct BindingContext {
+ BindingContext()
+ : stack(0), object(0) {}
+ BindingContext(QmlParser::Object *o)
+ : stack(0), object(o) {}
+ BindingContext incr() const {
+ BindingContext rv(object);
+ rv.stack = stack + 1;
+ return rv;
+ }
+ int stack;
+ QmlParser::Object *object;
+ };
+
void compileTree(QmlParser::Object *tree);
- bool compileObject(QmlParser::Object *obj, int);
- bool compileComponent(QmlParser::Object *obj, int);
- bool compileComponentFromRoot(QmlParser::Object *obj, int);
- bool compileFetchedObject(QmlParser::Object *obj, int);
+ bool compileObject(QmlParser::Object *obj, const BindingContext &);
+ bool compileComponent(QmlParser::Object *obj, const BindingContext &);
+ bool compileComponentFromRoot(QmlParser::Object *obj, const BindingContext &);
+ bool compileFetchedObject(QmlParser::Object *obj, const BindingContext &);
bool compileSignal(QmlParser::Property *prop, QmlParser::Object *obj);
bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj);
int signalByName(const QMetaObject *, const QByteArray &name);
- bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, int);
+ bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &);
bool compileIdProperty(QmlParser::Property *prop,
QmlParser::Object *obj);
bool compileAttachedProperty(QmlParser::Property *prop,
- int ctxt);
+ const BindingContext &ctxt);
bool compileNestedProperty(QmlParser::Property *prop,
- int ctxt);
+ const BindingContext &ctxt);
bool compileListProperty(QmlParser::Property *prop,
QmlParser::Object *obj,
- int ctxt);
+ const BindingContext &ctxt);
bool compilePropertyAssignment(QmlParser::Property *prop,
QmlParser::Object *obj,
- int ctxt);
+ const BindingContext &ctxt);
bool compilePropertyObjectAssignment(QmlParser::Property *prop,
QmlParser::Value *value,
- int ctxt);
+ const BindingContext &ctxt);
bool compilePropertyLiteralAssignment(QmlParser::Property *prop,
QmlParser::Object *obj,
QmlParser::Value *value,
- int ctxt);
+ const BindingContext &ctxt);
bool compileStoreInstruction(QmlInstruction &instr,
const QMetaProperty &prop,
QmlParser::Value *value);
bool compileDynamicMeta(QmlParser::Object *obj);
bool compileBinding(QmlParser::Value *, QmlParser::Property *prop,
- int ctxt);
+ const BindingContext &ctxt);
void finalizeComponent(int patch);
struct BindingReference;
@@ -169,6 +183,7 @@ private:
QString id;
QmlParser::Object *object;
int instructionIdx;
+ int idx;
};
struct BindingReference {
@@ -176,17 +191,18 @@ private:
QmlParser::Property *property;
QmlParser::Value *value;
int instructionIdx;
- int bindingContext;
+ BindingContext bindingContext;
};
struct ComponentCompileState
{
- ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0) {}
+ ComponentCompileState() : parserStatusCount(0), savedObjects(0), pushedProperties(0), root(0) {}
QHash<QString, IdReference> ids;
int parserStatusCount;
int savedObjects;
int pushedProperties;
QList<BindingReference> bindings;
+ QmlParser::Object *root;
};
ComponentCompileState compileState;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 73b9245..66781ce 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -219,30 +219,11 @@ QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
return old;
}
-QmlEnginePrivate::CapturedProperty::CapturedProperty(QObject *obj, int n)
-: object(obj), notifyIndex(n)
-{
-}
-
QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
-: object(p.object()), name(p.name()), notifyIndex(p.property().notifySignalIndex())
-{
-}
-
-QmlEnginePrivate::CapturedProperty::CapturedProperty(const CapturedProperty &o)
-: object(o.object), name(o.name), notifyIndex(o.notifyIndex)
+: object(p.object()), notifyIndex(p.property().notifySignalIndex())
{
}
-QmlEnginePrivate::CapturedProperty &
-QmlEnginePrivate::CapturedProperty::operator=(const CapturedProperty &o)
-{
- object = o.object;
- name = o.name;
- notifyIndex = o.notifyIndex;
- return *this;
-}
-
////////////////////////////////////////////////////////////////////
typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
Q_GLOBAL_STATIC(FunctionCache, functionCache);
@@ -1224,8 +1205,9 @@ QVariant QmlExpression::value()
QMetaObject::connect(prop.object, prop.notifyIndex,
d->proxy, changedIndex);
} else {
- QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name;
- log.addWarning(warn);
+ // ### FIXME
+ //QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name;
+ //log.addWarning(warn);
}
}
d->addLog(log);
@@ -1305,7 +1287,7 @@ void QmlExpression::setTrackChange(bool trackChange)
Set the location of this expression to \a line of \a fileName. This information
is used by the script engine.
*/
-void QmlExpression::setSourceLocation(const QString &fileName, int line)
+void QmlExpression::setSourceLocation(const QUrl &fileName, int line)
{
d->fileName = fileName;
d->line = line;
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index d7249e4..a1028e6 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -52,6 +52,7 @@
#include <private/qobject_p.h>
#include <private/qmlclassfactory_p.h>
#include <private/qmlcompositetypemanager_p.h>
+#include <private/qpodvector_p.h>
#include <QtDeclarative/qml.h>
#include <private/qmlbasicscript_p.h>
#include <QtDeclarative/qmlcontext.h>
@@ -90,16 +91,14 @@ public:
QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0);
struct CapturedProperty {
- CapturedProperty(QObject *, int);
+ CapturedProperty(QObject *o, int n)
+ : object(o), notifyIndex(n) {}
CapturedProperty(const QmlMetaProperty &);
- CapturedProperty(const CapturedProperty &);
- CapturedProperty &operator=(const CapturedProperty &);
QObject *object;
- QString name;
int notifyIndex;
};
- QList<CapturedProperty> capturedProperties;
+ QPODVector<CapturedProperty> capturedProperties;
QmlContext *rootContext;
QmlContext *currentBindContext;
@@ -280,7 +279,8 @@ public:
BindExpressionProxy *proxy;
QObject *me;
bool trackChange;
- QString fileName;
+
+ QUrl fileName;
int line;
quint32 id;
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
index 651fd9c..15d026a 100644
--- a/src/declarative/qml/qmlexpression.h
+++ b/src/declarative/qml/qmlexpression.h
@@ -77,7 +77,7 @@ public:
bool trackChange() const;
void setTrackChange(bool);
- void setSourceLocation(const QString &fileName, int line);
+ void setSourceLocation(const QUrl &fileName, int line);
QObject *scopeObject() const;
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index f00d282..9ed7e95 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -695,7 +695,7 @@ case QmlInstruction::StoreDouble:
QFx_setParent_noEvent(bind, target);
bind->setTarget(mp);
- bind->setSourceLocation(comp->url.toString(), instr.line);
+ bind->setSourceLocation(comp->url, instr.line);
}
break;
@@ -719,7 +719,7 @@ case QmlInstruction::StoreDouble:
QFx_setParent_noEvent(bind, target);
bind->setTarget(mp);
- bind->setSourceLocation(comp->url.toString(), instr.line);
+ bind->setSourceLocation(comp->url, instr.line);
}
break;
diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/qpodvector_p.h
new file mode 100644
index 0000000..55c04e7
--- /dev/null
+++ b/src/declarative/qml/qpodvector_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPODVECTOR_P_H
+#define QPODVECTOR_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+template<class T>
+class QPODVector
+{
+public:
+ QPODVector()
+ : m_count(0), m_capacity(0), m_data(0) {}
+
+ const T &at(int idx) {
+ return m_data[idx];
+ }
+
+ T &operator[](int idx) {
+ return m_data[idx];
+ }
+
+ void clear() {
+ m_count = 0;
+ }
+
+ void prepend(const T &v) {
+ insert(0, v);
+ }
+
+ void append(const T &v) {
+ insert(m_count, v);
+ }
+
+ void insert(int idx, const T &v) {
+ if (m_count == m_capacity) {
+ m_capacity += 1024;
+ m_data = (T *)realloc(m_data, m_capacity * sizeof(T));
+ }
+ int moveCount = m_count - idx;
+ if (moveCount)
+ ::memmove(m_data + idx + 1, m_data + idx, moveCount * sizeof(T));
+ m_count++;
+ m_data[idx] = v;
+ }
+
+ void insertBlank(int idx, int count) {
+ int newSize = m_count + count;
+ if (newSize >= m_capacity) {
+ m_capacity = (newSize + 1023) & 0xFFFFFC00;
+ m_data = (T *)realloc(m_data, m_capacity * sizeof(T));
+ }
+
+ int moveCount = m_count - idx;
+ if (moveCount)
+ ::memmove(m_data + idx + count, m_data + idx,
+ moveCount * sizeof(T));
+ m_count = newSize;
+ }
+
+ void remove(int idx, int count = 1) {
+ int moveCount = m_count - (idx + count);
+ if (moveCount)
+ ::memmove(m_data + idx, m_data + idx + count,
+ moveCount * sizeof(T));
+ m_count -= count;
+ }
+
+ int count() const {
+ return m_count;
+ }
+
+ QPODVector<T> &operator<<(const T &v) { append(v); return *this; }
+private:
+ QPODVector(const QPODVector &);
+ QPODVector &operator=(const QPODVector &);
+ int m_count;
+ int m_capacity;
+ T *m_data;
+};
+QT_END_NAMESPACE
+
+#endif