summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2010-03-12 02:23:50 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2010-03-12 02:24:48 (GMT)
commit93b789f196868f958b4d7dcfd45dbe27179b1b0f (patch)
treee53ab16dbd59b5cb53e7276d8375a0646c168760
parentc9042323b601d54c2cefaee0d28559c83d47841f (diff)
downloadQt-93b789f196868f958b4d7dcfd45dbe27179b1b0f.zip
Qt-93b789f196868f958b4d7dcfd45dbe27179b1b0f.tar.gz
Qt-93b789f196868f958b4d7dcfd45dbe27179b1b0f.tar.bz2
Reenable the QML binding optimizer for "safe" optimizations
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings.cpp72
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp29
-rw-r--r--src/declarative/qml/qdeclarativenotifier.cpp3
-rw-r--r--src/declarative/qml/qdeclarativeparser.cpp5
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h2
5 files changed, 81 insertions, 30 deletions
diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp
index c66a417..aa549a9 100644
--- a/src/declarative/qml/qdeclarativecompiledbindings.cpp
+++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp
@@ -48,12 +48,17 @@
#include <private/qdeclarativejsast_p.h>
#include <private/qdeclarativejsengine_p.h>
#include <private/qdeclarativeexpression_p.h>
+#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
#include <QtCore/qnumeric.h>
#include <private/qdeclarativeanchors_p_p.h>
+#include <private/qdeclarativeglobal_p.h>
QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER);
+
using namespace QDeclarativeJS;
namespace {
@@ -219,7 +224,6 @@ void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarati
{
if (e) {
addToObject(target);
- update(flags);
} else {
removeFromObject();
}
@@ -274,8 +278,6 @@ void QDeclarativeCompiledBindingsPrivate::run(Binding *binding)
if (!binding->enabled)
return;
- if (binding->updating)
- qWarning("ERROR: Circular binding");
QDeclarativeContext *context = q->QDeclarativeAbstractExpression::context();
if (!context) {
@@ -284,6 +286,25 @@ void QDeclarativeCompiledBindingsPrivate::run(Binding *binding)
}
QDeclarativeContextPrivate *cp = QDeclarativeContextPrivate::get(context);
+ if (binding->updating) {
+ QString name;
+ if (binding->property & 0xFFFF0000) {
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(cp->engine);
+
+ QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
+ Q_ASSERT(vt);
+
+ name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
+ name.append(QLatin1String("."));
+ name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
+ } else {
+ name = binding->target->metaObject()->property(binding->property).name();
+ }
+ qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeCompiledBindings", "Binding loop detected for property \"%1\"").arg(name);
+ return;
+ }
+
+ binding->updating = true;
if (binding->property & 0xFFFF0000) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(cp->engine);
@@ -299,6 +320,7 @@ void QDeclarativeCompiledBindingsPrivate::run(Binding *binding)
} else {
run(binding->index, cp, binding, binding->scope, binding->target);
}
+ binding->updating = false;
}
namespace {
@@ -624,6 +646,7 @@ void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextPrivate
QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
sub->target = q;
sub->targetMethod = methodCount + subIndex;
+ sub->connect(&p->idValues[idIndex].bindings);
}
}
@@ -634,7 +657,10 @@ void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex,
QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
sub->target = q;
sub->targetMethod = methodCount + subIndex;
- sub->connect(o, notifyIndex);
+ if (o)
+ sub->connect(o, notifyIndex);
+ else
+ sub->disconnect();
}
// Conversion functions - these MUST match the QtScript expression path
@@ -728,9 +754,9 @@ static QObject *variantToQObject(const QVariant &value, bool *ok)
}
bool QDeclarativeCompiledBindingsPrivate::findproperty(QObject *obj, Register *output,
- QDeclarativeEnginePrivate *enginePriv,
- int subIdx, const QScriptDeclarativeClass::Identifier &name,
- bool isTerminal)
+ QDeclarativeEnginePrivate *enginePriv,
+ int subIdx, const QScriptDeclarativeClass::Identifier &name,
+ bool isTerminal)
{
if (!obj) {
output->setUndefined();
@@ -801,10 +827,10 @@ bool QDeclarativeCompiledBindingsPrivate::findproperty(QObject *obj, Register *o
}
void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output,
- int subIdx,
- QDeclarativeContextPrivate *context,
- const QScriptDeclarativeClass::Identifier &name,
- bool isTerminal)
+ int subIdx,
+ QDeclarativeContextPrivate *context,
+ const QScriptDeclarativeClass::Identifier &name,
+ bool isTerminal)
{
QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context->engine);
@@ -1529,6 +1555,9 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node
return false;
if (type.unknownType) {
+ if (!qmlExperimental())
+ return false;
+
if (destination->type != QMetaType::QReal &&
destination->type != QVariant::String &&
destination->type != QMetaType::Bool &&
@@ -1812,7 +1841,7 @@ bool QDeclarativeBindingCompilerPrivate::parseName(AST::Node *node, Result &type
if (!fetch(type, component->metaObject(), reg, d1Idx, subscribeName, nameNodes.at(ii)))
return false;
- } else {
+ } else if (qmlExperimental()) {
Instr find;
if (nameParts.count() == 1)
find.common.type = Instr::FindGenericTerminal;
@@ -1968,7 +1997,11 @@ bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result
int lhsTmp = -1;
int rhsTmp = -1;
+
if (lhs.unknownType) {
+ if (!qmlExperimental())
+ return false;
+
lhsTmp = acquireReg();
Instr conv;
@@ -1979,6 +2012,9 @@ bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result
}
if (rhs.unknownType) {
+ if (!qmlExperimental())
+ return false;
+
rhsTmp = acquireReg();
Instr conv;
@@ -2024,6 +2060,9 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result
int rhsTmp = -1;
if (lhs.unknownType) {
+ if (!qmlExperimental())
+ return false;
+
lhsTmp = acquireReg(Instr::CleanupString);
Instr convert;
@@ -2034,6 +2073,9 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result
}
if (rhs.unknownType) {
+ if (!qmlExperimental())
+ return false;
+
rhsTmp = acquireReg(Instr::CleanupString);
Instr convert;
@@ -2554,6 +2596,12 @@ int QDeclarativeBindingCompiler::compile(const Expression &expression, QDeclarat
{
if (!expression.expression.asAST()) return false;
+ if (!qmlExperimental() && expression.property->isValueTypeSubProperty)
+ return -1;
+
+ if (qmlDisableOptimizer())
+ return -1;
+
d->context = expression.context;
d->component = expression.component;
d->destination = expression.property;
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index ef1032b..06ff47c 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -82,7 +82,7 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATISTICS_DUMP);
-DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
+DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP);
using namespace QDeclarativeParser;
@@ -1850,6 +1850,7 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
QMetaProperty p = type->metaObject()->property(idx);
prop->index = idx;
prop->type = p.userType();
+ prop->isValueTypeSubProperty = true;
if (prop->value)
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Property assignment expected"));
@@ -2712,7 +2713,9 @@ bool QDeclarativeCompiler::completeComponentBuild()
QDeclarativeBindingCompiler bindingCompiler;
- for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) {
+ for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin();
+ iter != compileState.bindings.end(); ++iter) {
+
BindingReference &binding = *iter;
expr.context = binding.bindingContext.object;
@@ -2720,18 +2723,13 @@ bool QDeclarativeCompiler::completeComponentBuild()
expr.expression = binding.expression;
expr.imports = unit->imports;
- if (qmlExperimental()) {
- int index = bindingCompiler.compile(expr, QDeclarativeEnginePrivate::get(engine));
- if (index != -1) {
- qWarning() << "Accepted for optimization:" << qPrintable(expr.expression.asScript());
- binding.dataType = BindingReference::Experimental;
- binding.compiledIndex = index;
- componentStat.optimizedBindings++;
- continue;
- } else {
- qWarning() << "Rejected for optimization:" << qPrintable(expr.expression.asScript());
- }
- }
+ int index = bindingCompiler.compile(expr, QDeclarativeEnginePrivate::get(engine));
+ if (index != -1) {
+ binding.dataType = BindingReference::Experimental;
+ binding.compiledIndex = index;
+ componentStat.optimizedBindings++;
+ continue;
+ }
binding.dataType = BindingReference::QtScript;
@@ -2768,7 +2766,8 @@ bool QDeclarativeCompiler::completeComponentBuild()
if (bindingCompiler.isValid()) {
compileState.compiledBindingData = bindingCompiler.program();
- QDeclarativeBindingCompiler::dump(compileState.compiledBindingData);
+ if (bindingsDump())
+ QDeclarativeBindingCompiler::dump(compileState.compiledBindingData);
}
saveComponentState();
diff --git a/src/declarative/qml/qdeclarativenotifier.cpp b/src/declarative/qml/qdeclarativenotifier.cpp
index 0a8783a..8e5904c 100644
--- a/src/declarative/qml/qdeclarativenotifier.cpp
+++ b/src/declarative/qml/qdeclarativenotifier.cpp
@@ -59,7 +59,8 @@ void QDeclarativeNotifier::emitNotify(QDeclarativeNotifierEndpoint *endpoint)
QMetaObject::metacall(endpoint->target, QMetaObject::InvokeMetaMethod,
endpoint->targetMethod, args);
- n->disconnected = oldDisconnected;
+ if (n)
+ n->disconnected = oldDisconnected;
}
if (oldDisconnected) *oldDisconnected = n;
diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp
index b0599ad..51f1660 100644
--- a/src/declarative/qml/qdeclarativeparser.cpp
+++ b/src/declarative/qml/qdeclarativeparser.cpp
@@ -207,13 +207,14 @@ QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o)
}
QDeclarativeParser::Property::Property()
-: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false)
+: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false),
+ isValueTypeSubProperty(false)
{
}
QDeclarativeParser::Property::Property(const QByteArray &n)
: parent(0), type(0), index(-1), value(0), name(n), isDefault(false),
- isDeferred(false)
+ isDeferred(false), isValueTypeSubProperty(false)
{
}
diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h
index 5bf4b68..9dfb86b 100644
--- a/src/declarative/qml/qdeclarativeparser_p.h
+++ b/src/declarative/qml/qdeclarativeparser_p.h
@@ -351,6 +351,8 @@ namespace QDeclarativeParser
// True if the setting of this property will be deferred. Set by the
// QDeclarativeCompiler
bool isDeferred;
+ // True if this property is a value-type psuedo-property
+ bool isValueTypeSubProperty;
LocationSpan location;
LocationRange listValueRange;