diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2010-03-12 02:23:50 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2010-03-12 02:24:48 (GMT) |
commit | 93b789f196868f958b4d7dcfd45dbe27179b1b0f (patch) | |
tree | e53ab16dbd59b5cb53e7276d8375a0646c168760 | |
parent | c9042323b601d54c2cefaee0d28559c83d47841f (diff) | |
download | Qt-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.cpp | 72 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativecompiler.cpp | 29 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativenotifier.cpp | 3 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeparser.cpp | 5 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeparser_p.h | 2 |
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; |