From 12ffa33ddc725cd94662a383af6e1793049c807c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 13:44:48 +1000 Subject: Simplify QmlDeclarativeData to a single class --- src/declarative/qml/qmlcontext.cpp | 11 +-- src/declarative/qml/qmlcontext.h | 1 - src/declarative/qml/qmlcontext_p.h | 3 +- src/declarative/qml/qmldeclarativedata_p.h | 113 +++++------------------------ src/declarative/qml/qmlengine.cpp | 37 ++++++---- src/declarative/qml/qmlvme.cpp | 6 +- 6 files changed, 46 insertions(+), 125 deletions(-) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 8a2732d..18ba906 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -106,8 +106,6 @@ void QmlContextPrivate::init() else scopeChain = parent->d_func()->scopeChain; scopeChain.prepend(scopeObj); - - contextData.context = q; } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) @@ -291,13 +289,10 @@ QmlContext::~QmlContext() for (int ii = 0; ii < d->contextObjects.count(); ++ii) { QObjectPrivate *p = QObjectPrivate::get(d->contextObjects.at(ii)); - QmlSimpleDeclarativeData *data = - static_cast(p->declarativeData); - if(data && (data->flags & QmlSimpleDeclarativeData::Extended)) { + QmlDeclarativeData *data = + static_cast(p->declarativeData); + if(data) data->context = 0; - } else { - p->declarativeData = 0; - } } d->contextObjects.clear(); diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index 1f29ca2..70a81fc 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -89,7 +89,6 @@ private: friend class QmlComponent; friend class QmlScriptPrivate; friend class QmlBoundSignalProxy; - friend class QmlSimpleDeclarativeData; QmlContext(QmlContext *parent, QObject *objParent, bool); QmlContext(QmlEngine *, bool); }; diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 60655ae..0424a85 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -106,7 +106,6 @@ public: QmlExpressionPrivate *expressions; - QmlSimpleDeclarativeData contextData; QObjectList contextObjects; struct ContextGuard : public QGuard @@ -115,7 +114,7 @@ public: ContextGuard &operator=(QObject *obj) { (QGuard&)*this = obj; return *this; } - void objectDestroyed(QObject *o) { priv->destroyed(this); } + void objectDestroyed(QObject *) { priv->destroyed(this); } }; ContextGuard *idValues; int idValueCount; diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index b473e77..8d30bcc 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -57,113 +57,36 @@ QT_BEGIN_NAMESPACE -class QmlSimpleDeclarativeData : public QDeclarativeData -{ -public: - QmlSimpleDeclarativeData() : flags(0), context(0) {} - - virtual void destroyed(QObject *); - enum Flag { Instance = 0x00000001, Extended = 0x00000002 }; - quint32 flags; - QmlContext *context; - - static inline QmlSimpleDeclarativeData *get(QObject *object, - bool create = false); -}; - class QmlCompiledData; -class QmlInstanceDeclarativeData : public QmlSimpleDeclarativeData +class QmlBinding; +class QmlDeclarativeData : public QDeclarativeData { public: - QmlInstanceDeclarativeData() : deferredComponent(0) { flags |= Instance; } + QmlDeclarativeData(QmlContext *context = 0); virtual void destroyed(QObject *); - QmlCompiledData *deferredComponent; - unsigned int deferredIdx; - - static inline QmlInstanceDeclarativeData *get(QObject *object, - bool create = false); -}; - -class QmlExtendedDeclarativeData : public QmlInstanceDeclarativeData -{ -public: - QmlExtendedDeclarativeData() { flags |= Extended; } - - QHash attachedProperties; - - static inline QmlExtendedDeclarativeData *get(QObject *object, - bool create = false); -}; - -QmlSimpleDeclarativeData * -QmlSimpleDeclarativeData::get(QObject *object, bool create) -{ - QObjectPrivate *priv = QObjectPrivate::get(object); - - if (create && !priv->declarativeData) - priv->declarativeData = new QmlInstanceDeclarativeData; - - return static_cast(priv->declarativeData); -} - -QmlInstanceDeclarativeData * -QmlInstanceDeclarativeData::get(QObject *object, bool create) -{ - QObjectPrivate *priv = QObjectPrivate::get(object); - - QmlSimpleDeclarativeData *simple = - static_cast(priv->declarativeData); - - if (simple && (simple->flags & Instance)) { - return static_cast(simple); - } else if (create && simple) { - QmlInstanceDeclarativeData *rv = new QmlInstanceDeclarativeData; - rv->context = simple->context; - simple->destroyed(object); - priv->declarativeData = rv; - return rv; - } else if (create) { - QmlInstanceDeclarativeData *rv = new QmlInstanceDeclarativeData; - priv->declarativeData = rv; - return rv; - } - return 0; -} - -QmlExtendedDeclarativeData * -QmlExtendedDeclarativeData::get(QObject *object, bool create) -{ - QObjectPrivate *priv = QObjectPrivate::get(object); + QmlContext *context; + QmlBinding *bindings; - QmlSimpleDeclarativeData *simple = - static_cast(priv->declarativeData); + QmlCompiledData *deferredComponent; // Can't this be found from the context? + unsigned int deferredIdx; - if (simple && (simple->flags & Extended)) { - return static_cast(simple); - } else if (create && simple) { - QmlExtendedDeclarativeData *rv = new QmlExtendedDeclarativeData; - rv->context = simple->context; + QHash *attachedProperties; - if (simple->flags & Instance) { - QmlInstanceDeclarativeData *instance = - static_cast(priv->declarativeData); - rv->deferredComponent = instance->deferredComponent; - rv->deferredIdx = instance->deferredIdx; - delete simple; + static QmlDeclarativeData *get(const QObject *object, bool create = false) { + QObjectPrivate *priv = + QObjectPrivate::get(const_cast(object)); + if (priv && priv->declarativeData) { + return static_cast(priv->declarativeData); + } else if (create && priv) { + priv->declarativeData = new QmlDeclarativeData; + return static_cast(priv->declarativeData); } else { - simple->destroyed(object); + return 0; } - priv->declarativeData = rv; - return rv; - } else if (create) { - QmlExtendedDeclarativeData *rv = new QmlExtendedDeclarativeData; - priv->declarativeData = rv; - return rv; } - return 0; -} +}; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 68ad655..09539bc 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -427,8 +427,8 @@ QmlContext *QmlEngine::contextForObject(const QObject *object) QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); - QmlSimpleDeclarativeData *data = - static_cast(priv->declarativeData); + QmlDeclarativeData *data = + static_cast(priv->declarativeData); return data?data->context:0; } @@ -444,8 +444,8 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) { QObjectPrivate *priv = QObjectPrivate::get(object); - QmlSimpleDeclarativeData *data = - static_cast(priv->declarativeData); + QmlDeclarativeData *data = + static_cast(priv->declarativeData); if (data && data->context) { qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext"); @@ -453,7 +453,7 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) } if (!data) { - priv->declarativeData = &context->d_func()->contextData; + priv->declarativeData = new QmlDeclarativeData(context); } else { data->context = context; } @@ -463,7 +463,7 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context) void qmlExecuteDeferred(QObject *object) { - QmlInstanceDeclarativeData *data = QmlInstanceDeclarativeData::get(object); + QmlDeclarativeData *data = QmlDeclarativeData::get(object); if (data && data->deferredComponent) { QmlVME vme; @@ -487,10 +487,9 @@ QmlEngine *qmlEngine(const QObject *obj) QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) { - QmlExtendedDeclarativeData *edata = - QmlExtendedDeclarativeData::get(const_cast(object), true); + QmlDeclarativeData *data = QmlDeclarativeData::get(object); - QObject *rv = edata->attachedProperties.value(id); + QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0; if (rv || !create) return rv; @@ -500,23 +499,29 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre rv = pf(const_cast(object)); - if (rv) - edata->attachedProperties.insert(id, rv); + if (rv) { + if (!data->attachedProperties) + data->attachedProperties = new QHash(); + data->attachedProperties->insert(id, rv); + } return rv; } -void QmlSimpleDeclarativeData::destroyed(QObject *object) +QmlDeclarativeData::QmlDeclarativeData(QmlContext *ctxt) +: context(ctxt), bindings(0), deferredComponent(0), attachedProperties(0) { - if (context) - context->d_func()->contextObjects.removeAll(object); } -void QmlInstanceDeclarativeData::destroyed(QObject *object) +void QmlDeclarativeData::destroyed(QObject *object) { - QmlSimpleDeclarativeData::destroyed(object); if (deferredComponent) deferredComponent->release(); + if (attachedProperties) + delete attachedProperties; + if (context) + static_cast(QObjectPrivate::get(context))->contextObjects.removeAll(object); + delete this; } diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index bf3b31a..ffe8591 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -111,7 +111,7 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp, int start, int cou void QmlVME::runDeferred(QObject *object) { - QmlInstanceDeclarativeData *data = QmlInstanceDeclarativeData::get(object); + QmlDeclarativeData *data = QmlDeclarativeData::get(object); if (!data || !data->context || !data->deferredComponent) return; @@ -725,8 +725,8 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData { if (instr.defer.deferCount) { QObject *target = stack.top(); - QmlInstanceDeclarativeData *data = - QmlInstanceDeclarativeData::get(target, true); + QmlDeclarativeData *data = + QmlDeclarativeData::get(target, true); comp->addref(); data->deferredComponent = comp; data->deferredIdx = ii; -- cgit v0.12 From 8c3405bbf65826f0ab0be0bd090d723f8efaa3af Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 10 Aug 2009 15:37:19 +1000 Subject: Abstract expression and binding APIs By splitting the interface through which the system interacts with bindings away from a specific implementation, we can introduce highly specialized implementations for specific optimizations. This commit also includes a sample optimization for object properties being assigned directly from a local id. --- src/declarative/qml/qml.pri | 6 +- src/declarative/qml/qmlbasicscript.cpp | 17 ++++ src/declarative/qml/qmlbasicscript_p.h | 3 + src/declarative/qml/qmlbinding.cpp | 82 +++++++++++++----- src/declarative/qml/qmlbinding.h | 36 ++++++-- src/declarative/qml/qmlbinding_p.h | 3 +- src/declarative/qml/qmlbindingoptimizations.cpp | 109 ++++++++++++++++++++++++ src/declarative/qml/qmlbindingoptimizations_p.h | 91 ++++++++++++++++++++ src/declarative/qml/qmlcompiler.cpp | 19 +++++ src/declarative/qml/qmlcompiler_p.h | 2 + src/declarative/qml/qmlcomponent.cpp | 4 +- src/declarative/qml/qmlcomponent_p.h | 2 +- src/declarative/qml/qmlcontext.cpp | 14 +-- src/declarative/qml/qmlcontext_p.h | 6 +- src/declarative/qml/qmldeclarativedata_p.h | 4 +- src/declarative/qml/qmlengine.cpp | 19 +++-- src/declarative/qml/qmlengine_p.h | 5 +- src/declarative/qml/qmlenginedebug.cpp | 2 +- src/declarative/qml/qmlexpression.cpp | 92 ++++++++++++-------- src/declarative/qml/qmlexpression_p.h | 25 ++++-- src/declarative/qml/qmlinstruction_p.h | 5 ++ src/declarative/qml/qmlmetaproperty.cpp | 63 ++++++-------- src/declarative/qml/qmlmetaproperty.h | 6 +- src/declarative/qml/qmlvme.cpp | 19 ++++- src/declarative/util/qmlsetproperties.cpp | 5 +- src/declarative/util/qmlstate.h | 4 +- src/declarative/util/qmlstate_p.h | 2 +- src/declarative/util/qmltransitionmanager.cpp | 2 - 28 files changed, 505 insertions(+), 142 deletions(-) create mode 100644 src/declarative/qml/qmlbindingoptimizations.cpp create mode 100644 src/declarative/qml/qmlbindingoptimizations_p.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 75e5692..575876f 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -29,7 +29,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlenginedebug.cpp \ qml/qmlrewrite.cpp \ qml/qmlbasicscript.cpp \ - qml/qmlvaluetype.cpp + qml/qmlvaluetype.cpp \ + qml/qmlbindingoptimizations.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -75,7 +76,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlenginedebug_p.h \ qml/qmlrewrite_p.h \ qml/qpodvector_p.h \ - qml/qmlvaluetype_p.h + qml/qmlvaluetype_p.h \ + qml/qmlbindingoptimizations_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 21860a5..8993845 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -697,6 +697,23 @@ QVariant QmlBasicScript::run(QmlContext *context, QObject *me) return stack.top(); } +bool QmlBasicScript::isSingleIdFetch() const +{ + if (!isValid()) + return false; + + return d->instructionCount == 1 && + d->instructions()[0].type == ScriptInstruction::LoadIdObject; +} + +int QmlBasicScript::singleIdFetchIndex() const +{ + if (!isSingleIdFetch()) + return -1; + + return d->instructions()[0].fetch.idx; +} + /*! Return a pointer to the script's compile data, or null if there is no data. */ diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index 92d58f9..d096746 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -98,6 +98,9 @@ public: QVariant run(QmlContext *, QObject *); + bool isSingleIdFetch() const; + int singleIdFetchIndex() const; + private: int flags; QmlBasicScriptPrivate *d; diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 41cef49..7c5b366 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -47,6 +47,8 @@ #include #include #include +#include +#include Q_DECLARE_METATYPE(QList); @@ -55,7 +57,7 @@ QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); QmlBindingPrivate::QmlBindingPrivate() -: inited(false), updating(false), enabled(true), mePtr(0) +: updating(false), enabled(false), mePtr(0) { } @@ -92,25 +94,6 @@ QmlMetaProperty QmlBinding::property() const return d->property; } -void QmlBinding::init() -{ - Q_D(QmlBinding); - - if (d->inited) - return; - d->inited = true; - update(); -} - -void QmlBinding::forceUpdate() -{ - Q_D(QmlBinding); - if (!d->inited) - init(); - else - update(); -} - void QmlBinding::update() { Q_D(QmlBinding); @@ -118,7 +101,7 @@ void QmlBinding::update() #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer bu; #endif - if (!d->inited || !d->enabled) + if (!d->enabled) return; if (!d->updating) { @@ -168,6 +151,20 @@ void QmlBinding::setEnabled(bool e) Q_D(QmlBinding); d->enabled = e; setTrackChange(e); + + if (e) { + d->mePtr = 0; + addToObject(d->property.object()); + update(); + } else { + removeFromObject(); + } +} + +int QmlBinding::propertyIndex() +{ + Q_D(QmlBinding); + return d->property.coreIndex(); } bool QmlBinding::enabled() const @@ -177,4 +174,47 @@ bool QmlBinding::enabled() const return d->enabled; } +QString QmlBinding::expression() const +{ + return QmlExpression::expression(); +} + +QmlAbstractBinding::QmlAbstractBinding() +: m_prevBinding(0), m_nextBinding(0) +{ +} + +QmlAbstractBinding::~QmlAbstractBinding() +{ + removeFromObject(); +} + +void QmlAbstractBinding::addToObject(QObject *object) +{ + removeFromObject(); + + if (object) { + QmlDeclarativeData *data = QmlDeclarativeData::get(object, true); + m_nextBinding = data->bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &data->bindings; + data->bindings = this; + } +} + +void QmlAbstractBinding::removeFromObject() +{ + if (m_prevBinding) { + *m_prevBinding = m_nextBinding; + if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; + m_prevBinding = 0; + m_nextBinding = 0; + } +} + +QString QmlAbstractBinding::expression() const +{ + return QLatin1String(""); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index c2182d5..ad25c16 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -54,9 +54,34 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QmlAbstractBinding +{ +public: + QmlAbstractBinding(); + virtual ~QmlAbstractBinding(); + + virtual QString expression() const; + + virtual void setEnabled(bool) = 0; + virtual int propertyIndex() = 0; + + virtual void update() = 0; + + void addToObject(QObject *); + void removeFromObject(); + +private: + friend class QmlDeclarativeData; + friend class QmlMetaProperty; + + QmlAbstractBinding **m_prevBinding; + QmlAbstractBinding *m_nextBinding; +}; + class QmlContext; class QmlBindingPrivate; -class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression +class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression, + public QmlAbstractBinding { Q_OBJECT public: @@ -67,12 +92,13 @@ public: void setTarget(const QmlMetaProperty &); QmlMetaProperty property() const; - void init(); - void forceUpdate(); - - void setEnabled(bool); bool enabled() const; + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool); + virtual int propertyIndex(); + virtual QString expression() const; + public Q_SLOTS: void update(); diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h index ec1a04a..767e6af 100644 --- a/src/declarative/qml/qmlbinding_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -65,13 +65,12 @@ class QmlBindingPrivate : public QmlExpressionPrivate public: QmlBindingPrivate(); - bool inited:1; bool updating:1; bool enabled:1; QmlMetaProperty property; - QmlBinding **mePtr; + QmlAbstractBinding **mePtr; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp new file mode 100644 index 0000000..235c034 --- /dev/null +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qmlbindingoptimizations_p.h" +#include + +QT_BEGIN_NAMESPACE + + +QmlBindingIdOptimization::QmlBindingIdOptimization(QObject *object, + int propertyIdx, + QmlContext *context, + int id) +: m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id) +{ + QmlAbstractExpression::setContext(context); +} + +void QmlBindingIdOptimization::setEnabled(bool e) +{ + if (e) { + addToObject(m_object); + update(); + } else { + removeFromObject(); + } +} + +int QmlBindingIdOptimization::propertyIndex() +{ + return m_propertyIdx; +} + +void QmlBindingIdOptimization::update() +{ + QmlContextPrivate *ctxtPriv = + static_cast(QObjectPrivate::get(context())); + + if (ctxtPriv) { + + if (!m_prev) { + m_next = ctxtPriv->idValues[m_id].bindings; + if (m_next) m_next->m_prev = &m_next; + + m_prev = &ctxtPriv->idValues[m_id].bindings; + ctxtPriv->idValues[m_id].bindings = this; + } + + QObject *o = ctxtPriv->idValues[m_id].data(); + void *a[] = { &o, 0 }; + QMetaObject::metacall(m_object, QMetaObject::WriteProperty, + m_propertyIdx, a); + } +} + +void QmlBindingIdOptimization::reset() +{ + if (m_prev) { + *m_prev = m_next; + if (m_next) m_next->m_prev = m_prev; + m_next = 0; + m_prev = 0; + } + + QObject *o = 0; + void *a[] = { &o, 0 }; + QMetaObject::metacall(m_object, QMetaObject::WriteProperty, + m_propertyIdx, a); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h new file mode 100644 index 0000000..f50972d --- /dev/null +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 QMLBINDINGOPTIMIZATIONS_P_H +#define QMLBINDINGOPTIMIZATIONS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QmlBindingIdOptimization : public QmlAbstractExpression, + public QmlAbstractBinding +{ +public: + QmlBindingIdOptimization(QObject *object, int propertyIdx, + QmlContext *context, int id); + + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool); + virtual int propertyIndex(); + virtual void update(); + + void reset(); + +private: + QmlBindingIdOptimization **m_prev; + QmlBindingIdOptimization *m_next; + + QObject *m_object; + int m_propertyIdx; + int m_id; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLBINDINGOPTIMIZATIONS_P_H + diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 1c535d4..7c0964b 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1394,6 +1394,7 @@ void QmlCompiler::addId(const QString &id, QmlParser::Object *obj) Q_ASSERT(obj->id == id); obj->idIndex = compileState.ids.count(); compileState.ids.insert(id, obj); + compileState.idIndexes.insert(obj->idIndex, obj); } void QmlCompiler::addBindingReference(const BindingReference &ref) @@ -2064,6 +2065,22 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, const BindingReference &ref = compileState.bindings.value(binding); QmlInstruction store; + + QmlBasicScript bs; + if (ref.isBasicScript) + bs.load(ref.compiledData.constData() + sizeof(quint32)); + if (bs.isSingleIdFetch()) { + int idIndex = bs.singleIdFetchIndex(); + QmlParser::Object *idObj = compileState.idIndexes.value(idIndex); + if (canCoerce(prop->type, idObj)) { + store.type = QmlInstruction::StoreIdOptBinding; + store.assignIdOptBinding.id = idIndex; + store.assignIdOptBinding.property = prop->index; + output->bytecode << store; + return; + } + } + store.type = QmlInstruction::StoreCompiledBinding; store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; @@ -2109,6 +2126,7 @@ bool QmlCompiler::completeComponentBuild() binding.compiledData = QByteArray(bs.compileData(), bs.compileDataSize()); type = QmlExpressionPrivate::BasicScriptEngineData; + binding.isBasicScript = true; } else { type = QmlExpressionPrivate::PreTransformedQtScriptData; @@ -2122,6 +2140,7 @@ bool QmlCompiler::completeComponentBuild() QByteArray((const char *)&length, sizeof(quint32)) + QByteArray((const char *)expression.constData(), expression.length() * sizeof(QChar)); + binding.isBasicScript = false; } binding.compiledData.prepend(QByteArray((const char *)&type, sizeof(quint32))); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 094c05a..3d79e32 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -236,6 +236,7 @@ private: QmlParser::Variant expression; QmlParser::Property *property; QmlParser::Value *value; + bool isBasicScript; QByteArray compiledData; BindingContext bindingContext; }; @@ -247,6 +248,7 @@ private: : parserStatusCount(0), savedObjects(0), pushedProperties(0), root(0) {} QHash ids; + QHash idIndexes; int parserStatusCount; int savedObjects; int pushedProperties; diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index d4e383d..c30efca 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -533,11 +533,11 @@ void QmlComponent::completeCreate() QFxPerfTimer bi; #endif for (int ii = 0; ii < d->bindValues.count(); ++ii) { - QmlEnginePrivate::SimpleList bv = + QmlEnginePrivate::SimpleList bv = d->bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) - bv.at(jj)->init(); + bv.at(jj)->setEnabled(true); } QmlEnginePrivate::clear(bv); } diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index a7a3230..4b459c2 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -88,7 +88,7 @@ public: int count; QmlCompiledData *cc; - QList > bindValues; + QList > bindValues; QList > parserStatus; bool completePending; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 18ba906..451dbcc 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -47,6 +47,7 @@ #include #include #include +#include // 6-bits #define MAXIMUM_DEFAULT_OBJECTS 63 @@ -82,6 +83,9 @@ void QmlContextPrivate::destroyed(ContextGuard *guard) if (parent && QObjectPrivate::get(parent)->wasDeleted) return; + while(guard->bindings) + guard->bindings->reset(); + for (int ii = 0; ii < idValueCount; ++ii) { if (&idValues[ii] == guard) { QMetaObject::activate(q, ii + notifyIndex, 0); @@ -276,13 +280,13 @@ QmlContext::~QmlContext() (*iter)->d_func()->parent = 0; } - QmlExpressionPrivate *expression = d->expressions; + QmlAbstractExpression *expression = d->expressions; while (expression) { - QmlExpressionPrivate *nextExpression = expression->nextExpression; + QmlAbstractExpression *nextExpression = expression->m_nextExpression; - expression->ctxt = 0; - expression->prevExpression = 0; - expression->nextExpression = 0; + expression->m_context = 0; + expression->m_prevExpression = 0; + expression->m_nextExpression = 0; expression = nextExpression; } diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 0424a85..b5479d9 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -68,6 +68,8 @@ class QmlExpression; class QmlEngine; class QmlExpression; class QmlExpressionPrivate; +class QmlAbstractExpression; +class QmlBindingIdOptimization; class QmlContextPrivate : public QObjectPrivate { @@ -104,13 +106,15 @@ public: void invalidateEngines(); QSet childContexts; - QmlExpressionPrivate *expressions; + QmlAbstractExpression *expressions; QObjectList contextObjects; struct ContextGuard : public QGuard { + ContextGuard() : priv(0), bindings(0) {} QmlContextPrivate *priv; + QmlBindingIdOptimization *bindings; ContextGuard &operator=(QObject *obj) { (QGuard&)*this = obj; return *this; } diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index 8d30bcc..5a51eb7 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE class QmlCompiledData; -class QmlBinding; +class QmlAbstractBinding; class QmlDeclarativeData : public QDeclarativeData { public: @@ -67,7 +67,7 @@ public: virtual void destroyed(QObject *); QmlContext *context; - QmlBinding *bindings; + QmlAbstractBinding *bindings; QmlCompiledData *deferredComponent; // Can't this be found from the context? unsigned int deferredIdx; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 09539bc..bdbf2e7 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -121,16 +121,8 @@ QmlEnginePrivate::~QmlEnginePrivate() clear(parserStatus[ii]); } -void QmlEnginePrivate::clear(SimpleList &bvs) +void QmlEnginePrivate::clear(SimpleList &bvs) { - for (int ii = 0; ii < bvs.count; ++ii) { - QmlBinding *bv = bvs.at(ii); - if(bv) { - QmlBindingPrivate *p = - static_cast(QObjectPrivate::get(bv)); - p->mePtr = 0; - } - } bvs.clear(); } @@ -522,6 +514,15 @@ void QmlDeclarativeData::destroyed(QObject *object) if (context) static_cast(QObjectPrivate::get(context))->contextObjects.removeAll(object); + QmlAbstractBinding *binding = bindings; + while (binding) { + QmlAbstractBinding *next = binding->m_nextBinding; + binding->m_prevBinding = 0; + binding->m_nextBinding = 0; + delete binding; + binding = next; + } + delete this; } diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 602321d..d2e3ef4 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -86,6 +86,7 @@ class QmlValueTypeScriptClass; class QScriptEngineDebugger; class QNetworkReply; class QNetworkAccessManager; +class QmlAbstractBinding; class QmlEnginePrivate : public QObjectPrivate { @@ -160,10 +161,10 @@ public: } }; - static void clear(SimpleList &); + static void clear(SimpleList &); static void clear(SimpleList &); - QList > bindValues; + QList > bindValues; QList > parserStatus; QmlComponent *rootComponent; diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index c26f3b7..0e78cad 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -97,7 +97,7 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) rv.type = QmlObjectProperty::Unknown; rv.name = prop.name(); - QmlBinding *binding = QmlMetaProperty(obj, rv.name).binding(); + QmlAbstractBinding *binding = QmlMetaProperty(obj, rv.name).binding(); if (binding) rv.binding = binding->expression(); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 6e9a7a1..f8e78d7 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -51,33 +51,23 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE QmlExpressionPrivate::QmlExpressionPrivate() -: nextExpression(0), prevExpression(0), ctxt(0), expressionFunctionValid(false), expressionRewritten(false), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0) +: expressionFunctionValid(false), expressionRewritten(false), me(0), + trackChange(true), line(-1), guardList(0), guardListLength(0) { } void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, QObject *me) { - Q_Q(QmlExpression); - expression = expr; - this->ctxt = ctxt; - if (ctxt) { - QmlContextPrivate *cp = ctxt->d_func(); - nextExpression = cp->expressions; - if (nextExpression) nextExpression->prevExpression = &nextExpression; - prevExpression = &cp->expressions; - cp->expressions = this; - } + QmlAbstractExpression::setContext(ctxt); this->me = me; } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me) { - Q_Q(QmlExpression); - quint32 *data = (quint32 *)expr; Q_ASSERT(*data == BasicScriptEngineData || *data == PreTransformedQtScriptData); @@ -88,14 +78,7 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, expressionRewritten = true; } - this->ctxt = ctxt; - if (ctxt) { - QmlContextPrivate *cp = ctxt->d_func(); - nextExpression = cp->expressions; - if (nextExpression) nextExpression->prevExpression = &nextExpression; - prevExpression = &cp->expressions; - cp->expressions = this; - } + QmlAbstractExpression::setContext(ctxt); this->me = me; } @@ -159,12 +142,6 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression, */ QmlExpression::~QmlExpression() { - Q_D(QmlExpression); - if (d->prevExpression) { - *(d->prevExpression) = d->nextExpression; - if (d->nextExpression) - d->nextExpression->prevExpression = d->prevExpression; - } } /*! @@ -174,7 +151,7 @@ QmlExpression::~QmlExpression() QmlEngine *QmlExpression::engine() const { Q_D(const QmlExpression); - return d->ctxt?d->ctxt->engine():0; + return d->context()?d->context()->engine():0; } /*! @@ -184,7 +161,7 @@ QmlEngine *QmlExpression::engine() const QmlContext *QmlExpression::context() const { Q_D(const QmlExpression); - return d->ctxt; + return d->context(); } /*! @@ -230,9 +207,7 @@ QVariant QmlExpressionPrivate::evalSSE() QFxPerfTimer perfsse; #endif - QmlContextPrivate *ctxtPriv = ctxt->d_func(); - - QVariant rv = sse.run(ctxt, me); + QVariant rv = sse.run(context(), me); return rv; } @@ -243,8 +218,8 @@ QVariant QmlExpressionPrivate::evalQtScript() QFxPerfTimer perfqt; #endif - QmlContextPrivate *ctxtPriv = ctxt->d_func(); - QmlEngine *engine = ctxt->engine(); + QmlContextPrivate *ctxtPriv = context()->d_func(); + QmlEngine *engine = context()->engine(); if (me) ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, me); @@ -347,7 +322,7 @@ QVariant QmlExpression::value() Q_D(QmlExpression); QVariant rv; - if (!d->ctxt || !engine() || (!d->sse.isValid() && d->expression.isEmpty())) + if (!d->context() || (!d->sse.isValid() && d->expression.isEmpty())) return rv; #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -574,5 +549,52 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorm_prevExpression = m_prevExpression; + } +} + +QmlContext *QmlAbstractExpression::context() const +{ + return m_context; +} + +void QmlAbstractExpression::setContext(QmlContext *context) +{ + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + m_prevExpression = 0; + m_nextExpression = 0; + } + + m_context = context; + + if (m_context) { + QmlContextPrivate *cp = + static_cast(QObjectPrivate::get(m_context)); + m_nextExpression = cp->expressions; + if (m_nextExpression) + m_nextExpression->m_prevExpression = &m_nextExpression; + m_prevExpression = &cp->expressions; + cp->expressions = this; + } +} + +bool QmlAbstractExpression::isValid() const +{ + return m_context != 0; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index bf95c0e0..997bf8d 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -61,19 +61,33 @@ QT_BEGIN_NAMESPACE +class QmlAbstractExpression +{ +public: + QmlAbstractExpression(); + virtual ~QmlAbstractExpression(); + + bool isValid() const; + + QmlContext *context() const; + void setContext(QmlContext *); + +private: + friend class QmlContext; + QmlContext *m_context; + QmlAbstractExpression **m_prevExpression; + QmlAbstractExpression *m_nextExpression; +}; + class QmlExpression; class QString; -class QmlExpressionPrivate : public QObjectPrivate +class QmlExpressionPrivate : public QObjectPrivate, public QmlAbstractExpression { Q_DECLARE_PUBLIC(QmlExpression) public: QmlExpressionPrivate(); ~QmlExpressionPrivate(); - // Forms the QmlContext "expressions" linked list - QmlExpressionPrivate *nextExpression; - QmlExpressionPrivate **prevExpression; - enum CompiledDataType { BasicScriptEngineData = 1, PreTransformedQtScriptData = 2 @@ -82,7 +96,6 @@ public: void init(QmlContext *, const QString &, QObject *); void init(QmlContext *, void *, QmlRefCount *, QObject *); - QmlContext *ctxt; QString expression; bool expressionFunctionValid:1; bool expressionRewritten:1; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index e6b8de6..16bc8cf 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -125,6 +125,7 @@ public: AssignCustomType, /* assignCustomType */ StoreCompiledBinding, /* assignBinding */ + StoreIdOptBinding, /* assignIdOptBinding */ StoreValueSource, /* assignValueSource */ BeginObject, /* begin */ @@ -189,6 +190,10 @@ public: } assignBinding; struct { int property; + int id; + } assignIdOptBinding; + struct { + int property; } fetch; struct { int property; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 64dd9cd..d986077 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -51,6 +51,7 @@ #include #include #include +#include Q_DECLARE_METATYPE(QList); @@ -509,20 +510,21 @@ QMetaProperty QmlMetaProperty::property() const Returns the binding associated with this property, or 0 if no binding exists. */ -QmlBinding *QmlMetaProperty::binding() const +QmlAbstractBinding *QmlMetaProperty::binding() const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - const QObjectList &children = object()->children(); - for (QObjectList::ConstIterator iter = children.begin(); - iter != children.end(); ++iter) { - QObject *child = *iter; - if (child->metaObject() == &QmlBinding::staticMetaObject) { - QmlBinding *v = static_cast(child); - if (v->property() == *this && v->enabled()) - return v; - } + QmlDeclarativeData *data = QmlDeclarativeData::get(d->object); + if (!data) + return 0; + + QmlAbstractBinding *binding = data->bindings; + while (binding) { + // ### This wont work for value types + if (binding->propertyIndex() == d->coreIdx) + return binding; + binding = binding->m_nextBinding; } return 0; } @@ -534,41 +536,32 @@ QmlBinding *QmlMetaProperty::binding() const \a binding will be enabled, and the returned binding (if any) will be disabled. */ -QmlBinding *QmlMetaProperty::setBinding(QmlBinding *binding) const +QmlAbstractBinding * +QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - const QObjectList &children = object()->children(); - for (QObjectList::ConstIterator iter = children.begin(); - iter != children.end(); ++iter) { - QObject *child = *iter; - if (child->metaObject() == &QmlBinding::staticMetaObject) { - QmlBinding *v = static_cast(child); - if (v->property() == *this && v->enabled()) { - - v->setEnabled(false); - - if (binding) { - binding->setParent(object()); - binding->setTarget(*this); - binding->setEnabled(true); - binding->forceUpdate(); - } + QmlDeclarativeData *data = QmlDeclarativeData::get(d->object, true); - return v; + QmlAbstractBinding *binding = data->bindings; + while (binding) { + // ### This wont work for value types + if (binding->propertyIndex() == d->coreIdx) { + binding->setEnabled(false); - } + if (newBinding) + newBinding->setEnabled(true); + + return binding; // ### QmlAbstractBinding; } - } - if (binding) { - binding->setParent(object()); - binding->setTarget(*this); - binding->setEnabled(true); - binding->forceUpdate(); + binding = binding->m_nextBinding; } + if (newBinding) + newBinding->setEnabled(true); + return 0; } diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 434ff55..7b9ff47 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QObject; -class QmlBinding; +class QmlAbstractBinding; class QStringList; class QVariant; struct QMetaObject; @@ -122,8 +122,8 @@ public: QMetaProperty property() const; - QmlBinding *binding() const; - QmlBinding *setBinding(QmlBinding *) const; + QmlAbstractBinding *binding() const; + QmlAbstractBinding *setBinding(QmlAbstractBinding *) const; static QmlMetaProperty createProperty(QObject *, const QString &); diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index ffe8591..dccf5c4 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -65,6 +65,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -138,7 +139,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData const QList &floatData = comp->floatData; - QmlEnginePrivate::SimpleList bindValues; + QmlEnginePrivate::SimpleList bindValues; QmlEnginePrivate::SimpleList parserStatus; QStack qliststack; @@ -154,7 +155,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::Init: { if (instr.init.bindingsSize) - bindValues = QmlEnginePrivate::SimpleList(instr.init.bindingsSize); + bindValues = QmlEnginePrivate::SimpleList(instr.init.bindingsSize); if (instr.init.parserStatusSize) parserStatus = QmlEnginePrivate::SimpleList(instr.init.parserStatusSize); @@ -543,12 +544,24 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData QmlBindingPrivate *p = static_cast(QObjectPrivate::get(bind)); p->mePtr = &bindValues.values[bindValues.count - 1]; - QFx_setParent_noEvent(bind, target); + bind->addToObject(target); bind->setTarget(mp); } break; + case QmlInstruction::StoreIdOptBinding: + { + QObject *target = stack.top(); + + QmlBindingIdOptimization *bind = + new QmlBindingIdOptimization(target, instr.assignIdOptBinding.property, ctxt, instr.assignIdOptBinding.id); + bindValues.append(bind); + // ### Need a mePtr + bind->addToObject(target); + } + break; + case QmlInstruction::StoreValueSource: { QmlPropertyValueSource *vs = diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp index 1cd4a79..482405c 100644 --- a/src/declarative/util/qmlsetproperties.cpp +++ b/src/declarative/util/qmlsetproperties.cpp @@ -334,9 +334,10 @@ QmlSetProperties::ActionList QmlSetProperties::actions() if (d->isExplicit) { a.toValue = d->expressions.at(ii).second->value(); } else { - a.toBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + QmlBinding *newBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + newBinding->setTarget(prop); + a.toBinding = newBinding; a.deletableToBinding = true; - a.toBinding->setTarget(prop); } list << a; diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 9eb7aee..46659c6 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -70,8 +70,8 @@ public: QVariant fromValue; QVariant toValue; - QmlBinding *fromBinding; - QmlBinding *toBinding; + QmlAbstractBinding *fromBinding; + QmlAbstractBinding *toBinding; ActionEvent *event; //strictly for matching diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h index b601b57..63fc6da 100644 --- a/src/declarative/util/qmlstate_p.h +++ b/src/declarative/util/qmlstate_p.h @@ -83,7 +83,7 @@ public: QmlMetaProperty property; QVariant value; - QmlBinding *binding; + QmlAbstractBinding *binding; QObject *specifiedObject; QString specifiedProperty; ActionEvent *event; diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index f04a821..3e2e05f 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -94,7 +94,6 @@ void QmlTransitionManagerPrivate::applyBindings() foreach(const Action &action, bindingsList) { if (action.toBinding) { action.property.setBinding(action.toBinding); - action.toBinding->forceUpdate(); } else if (action.event) { if (action.reverseEvent) action.event->reverse(); @@ -146,7 +145,6 @@ void QmlTransitionManager::transition(const QList &list, const Action &action = applyList.at(ii); if (action.toBinding) { action.property.setBinding(action.toBinding); - action.toBinding->forceUpdate(); } else if (!action.event) { action.property.write(action.toValue); } else if (action.event->isReversable()) { -- cgit v0.12 From a57bcdde329ef4c9a71aa6ba714f5e30ffd5dc6d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 11 Aug 2009 13:59:56 +1000 Subject: Object property binding optimization Add a binding optimization that hits anchors.fill: parent --- src/declarative/qml/qmlbasicscript.cpp | 17 +++++ src/declarative/qml/qmlbasicscript_p.h | 2 + src/declarative/qml/qmlbindingoptimizations.cpp | 92 ++++++++++++++++++++++--- src/declarative/qml/qmlbindingoptimizations_p.h | 35 ++++++++-- src/declarative/qml/qmlcompiler.cpp | 40 ++++++++++- src/declarative/qml/qmlcompiler_p.h | 1 + src/declarative/qml/qmlcontext_p.h | 4 +- src/declarative/qml/qmlinstruction.cpp | 2 +- src/declarative/qml/qmlinstruction_p.h | 11 ++- src/declarative/qml/qmlvme.cpp | 22 +++++- 10 files changed, 202 insertions(+), 24 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index 8993845..f3f9289 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -714,6 +714,23 @@ int QmlBasicScript::singleIdFetchIndex() const return d->instructions()[0].fetch.idx; } +bool QmlBasicScript::isSingleContextProperty() const +{ + if (!isValid()) + return false; + + return d->instructionCount == 1 && + d->instructions()[0].type == ScriptInstruction::FetchContextConstant; +} + +int QmlBasicScript::singleContextPropertyIndex() const +{ + if (!isSingleContextProperty()) + return -1; + + return d->instructions()[0].constant.idx; +} + /*! Return a pointer to the script's compile data, or null if there is no data. */ diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h index d096746..5ad7735 100644 --- a/src/declarative/qml/qmlbasicscript_p.h +++ b/src/declarative/qml/qmlbasicscript_p.h @@ -101,6 +101,8 @@ public: bool isSingleIdFetch() const; int singleIdFetchIndex() const; + bool isSingleContextProperty() const; + int singleContextPropertyIndex() const; private: int flags; QmlBasicScriptPrivate *d; diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index 235c034..a10b1e3 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -44,17 +44,27 @@ QT_BEGIN_NAMESPACE +/* + The QmlBinding_Id optimization handles expressions of the type: -QmlBindingIdOptimization::QmlBindingIdOptimization(QObject *object, - int propertyIdx, - QmlContext *context, - int id) + property: id + + where id is a local context id, and property is an object property. + Coercian between id and property must be checked outside the QmlBinding_Id - + it assumes that they coerce successfully. + + The QmlBinding_Id class avoids any signal slot connections, through the + special "bindings" linked list maintained in the + QmlContextPrivate::ContextGuard instance for each id object. +*/ +QmlBinding_Id::QmlBinding_Id(QObject *object, int propertyIdx, + QmlContext *context, int id) : m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id) { QmlAbstractExpression::setContext(context); } -void QmlBindingIdOptimization::setEnabled(bool e) +void QmlBinding_Id::setEnabled(bool e) { if (e) { addToObject(m_object); @@ -64,12 +74,12 @@ void QmlBindingIdOptimization::setEnabled(bool e) } } -int QmlBindingIdOptimization::propertyIndex() +int QmlBinding_Id::propertyIndex() { return m_propertyIdx; } -void QmlBindingIdOptimization::update() +void QmlBinding_Id::update() { QmlContextPrivate *ctxtPriv = static_cast(QObjectPrivate::get(context())); @@ -91,7 +101,7 @@ void QmlBindingIdOptimization::update() } } -void QmlBindingIdOptimization::reset() +void QmlBinding_Id::reset() { if (m_prev) { *m_prev = m_next; @@ -106,4 +116,70 @@ void QmlBindingIdOptimization::reset() m_propertyIdx, a); } +/* + The QmlBinding_ObjectProperty optimization handles expressions of the type: + + property: objectProperty + + where both property and objectProperty are object properties on the target + object. Coercian between the two must be checked outside the + QmlBinding_ObjectProperty - it assumes that they coerce successfully. + + Due to dot properties, property does not have to be on the same object as + objectProperty. For example: + + anchors.fill: parent +*/ +QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx, + QObject *context, int contextIdx, + int notifyIdx) +: m_enabled(false), m_object(object), m_propertyIdx(propertyIdx), + m_context(context), m_contextIdx(contextIdx), m_notifyIdx(notifyIdx) +{ +} + +void QmlBinding_ObjProperty::setEnabled(bool e) +{ + m_enabled = e; + if (e) { + addToObject(m_object); + update(); + } else { + removeFromObject(); + } +} + +int QmlBinding_ObjProperty::propertyIndex() +{ + return m_propertyIdx; +} + +void QmlBinding_ObjProperty::update() +{ + if (!m_enabled) + return; + + QObject *value = 0; + void *a[] = { &value, 0 }; + + // Read + QMetaObject::metacall(m_context, QMetaObject::ReadProperty, + m_contextIdx, a); + + // Write + QMetaObject::metacall(m_object, QMetaObject::WriteProperty, + m_propertyIdx, a); + + // Connect notify if needed. Only need to connect once, so we set + // m_notifyIdx back to -1 afterwards + static int slotIdx = -1; + if (m_notifyIdx != -1) { + if (slotIdx == -1) + slotIdx = QmlBinding_ObjProperty::staticMetaObject.indexOfMethod("update()"); + + QMetaObject::connect(m_context, m_notifyIdx, this, slotIdx); + m_notifyIdx = -1; + } +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h index f50972d..2d2ffec 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -60,11 +60,11 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QmlBindingIdOptimization : public QmlAbstractExpression, - public QmlAbstractBinding +class QmlBinding_Id : public QmlAbstractExpression, + public QmlAbstractBinding { public: - QmlBindingIdOptimization(QObject *object, int propertyIdx, + QmlBinding_Id(QObject *object, int propertyIdx, QmlContext *context, int id); // Inherited from QmlAbstractBinding @@ -75,14 +75,39 @@ public: void reset(); private: - QmlBindingIdOptimization **m_prev; - QmlBindingIdOptimization *m_next; + QmlBinding_Id **m_prev; + QmlBinding_Id *m_next; QObject *m_object; int m_propertyIdx; int m_id; }; +class QmlBinding_ObjProperty : public QObject, + public QmlAbstractExpression, + public QmlAbstractBinding +{ + Q_OBJECT +public: + QmlBinding_ObjProperty(QObject *object, int propertyIdx, + QObject *context, int contextIdx, int notifyIdx); + + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool); + virtual int propertyIndex(); + +private slots: + virtual void update(); + +private: + bool m_enabled; + QObject *m_object; + int m_propertyIdx; + QObject *m_context; + int m_contextIdx; + int m_notifyIdx; +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 7c0964b..75ed94b 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2069,6 +2069,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, QmlBasicScript bs; if (ref.isBasicScript) bs.load(ref.compiledData.constData() + sizeof(quint32)); + if (bs.isSingleIdFetch()) { int idIndex = bs.singleIdFetchIndex(); QmlParser::Object *idObj = compileState.idIndexes.value(idIndex); @@ -2079,9 +2080,26 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, output->bytecode << store; return; } + } else if (bs.isSingleContextProperty()) { + int propIndex = bs.singleContextPropertyIndex(); + + QMetaProperty p = + ref.bindingContext.object->metaObject()->property(propIndex); + if ((p.notifySignalIndex() != -1 || p.isConstant()) && + canCoerce(prop->type, p.userType())) { + + store.type = QmlInstruction::StoreObjPropBinding; + store.assignObjPropBinding.property = prop->index; + store.assignObjPropBinding.contextIdx = propIndex; + store.assignObjPropBinding.context = ref.bindingContext.stack; + store.assignObjPropBinding.notifyIdx = p.notifySignalIndex(); + + output->bytecode << store; + return; + } } - store.type = QmlInstruction::StoreCompiledBinding; + store.type = QmlInstruction::StoreBinding; store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; @@ -2157,8 +2175,7 @@ bool QmlCompiler::completeComponentBuild() */ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) { - const QMetaObject *toMo = - QmlMetaType::rawMetaObjectForType(to); + const QMetaObject *toMo = QmlMetaType::rawMetaObjectForType(to); const QMetaObject *fromMo = from->metaObject(); while (fromMo) { @@ -2169,6 +2186,23 @@ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) return false; } +/*! + Returns true if from can be assigned to a (QObject) property of type + to. +*/ +bool QmlCompiler::canCoerce(int to, int from) +{ + const QMetaObject *toMo = QmlMetaType::rawMetaObjectForType(to); + const QMetaObject *fromMo = QmlMetaType::rawMetaObjectForType(from); + + while (fromMo) { + if (fromMo == toMo) + return true; + fromMo = fromMo->superClass(); + } + return false; +} + QmlType *QmlCompiler::toQmlType(QmlParser::Object *from) { // ### Optimize diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 3d79e32..4f56169 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -226,6 +226,7 @@ private: static int findSignalByName(const QMetaObject *, const QByteArray &name); static bool canCoerce(int to, QmlParser::Object *from); + static bool canCoerce(int to, int from); static QmlType *toQmlType(QmlParser::Object *from); QStringList deferredProperties(QmlParser::Object *); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index b5479d9..84d990c 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -69,7 +69,7 @@ class QmlEngine; class QmlExpression; class QmlExpressionPrivate; class QmlAbstractExpression; -class QmlBindingIdOptimization; +class QmlBinding_Id; class QmlContextPrivate : public QObjectPrivate { @@ -114,7 +114,7 @@ public: { ContextGuard() : priv(0), bindings(0) {} QmlContextPrivate *priv; - QmlBindingIdOptimization *bindings; + QmlBinding_Id *bindings; ContextGuard &operator=(QObject *obj) { (QGuard&)*this = obj; return *this; } diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 889a057..fd912ac 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -140,7 +140,7 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::AssignCustomType: qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex; break; - case QmlInstruction::StoreCompiledBinding: + case QmlInstruction::StoreBinding: qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context; break; case QmlInstruction::StoreValueSource: diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 16bc8cf..7f3498f 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -122,10 +122,11 @@ public: // Unresolved single assignment // AssignSignalObject, /* assignSignalObject */ - AssignCustomType, /* assignCustomType */ + AssignCustomType, /* assignCustomType */ - StoreCompiledBinding, /* assignBinding */ + StoreBinding, /* assignBinding */ StoreIdOptBinding, /* assignIdOptBinding */ + StoreObjPropBinding, /* assignObjPropBinding */ StoreValueSource, /* assignValueSource */ BeginObject, /* begin */ @@ -194,6 +195,12 @@ public: } assignIdOptBinding; struct { int property; + int contextIdx; + short context; + short notifyIdx; + } assignObjPropBinding; + struct { + int property; } fetch; struct { int property; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index dccf5c4..fdfeddc 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -529,7 +529,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData } break; - case QmlInstruction::StoreCompiledBinding: + case QmlInstruction::StoreBinding: { QObject *target = stack.at(stack.count() - 1 - instr.assignBinding.owner); @@ -554,14 +554,30 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData { QObject *target = stack.top(); - QmlBindingIdOptimization *bind = - new QmlBindingIdOptimization(target, instr.assignIdOptBinding.property, ctxt, instr.assignIdOptBinding.id); + QmlBinding_Id *bind = + new QmlBinding_Id(target, instr.assignIdOptBinding.property, + ctxt, instr.assignIdOptBinding.id); bindValues.append(bind); // ### Need a mePtr bind->addToObject(target); } break; + case QmlInstruction::StoreObjPropBinding: + { + QObject *target = stack.top(); + QObject *context = + stack.at(stack.count() - 1 - instr.assignObjPropBinding.context); + + QmlBinding_ObjProperty *bind = + new QmlBinding_ObjProperty(target, instr.assignObjPropBinding.property, context, instr.assignObjPropBinding.contextIdx, instr.assignObjPropBinding.notifyIdx); + + bindValues.append(bind); + // ### Need a mePtr + bind->addToObject(target); + } + break; + case QmlInstruction::StoreValueSource: { QmlPropertyValueSource *vs = -- cgit v0.12 From fed8d73b0752b5f737082c534d39f350ca737a7b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 11 Aug 2009 14:15:30 +1000 Subject: Move the binding's "mePtr" into QmlAbstractBinding Now optimizations get deletion protection too. --- src/declarative/qml/qmlbinding.cpp | 17 +++++++++++------ src/declarative/qml/qmlbinding.h | 2 ++ src/declarative/qml/qmlbinding_p.h | 2 -- src/declarative/qml/qmlbindingoptimizations.cpp | 4 ++++ src/declarative/qml/qmlvme.cpp | 8 +++----- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 7c5b366..45d20f4 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); QmlBindingPrivate::QmlBindingPrivate() -: updating(false), enabled(false), mePtr(0) +: updating(false), enabled(false) { } @@ -75,9 +75,6 @@ QmlBinding::QmlBinding(const QString &str, QObject *obj, QmlContext *ctxt, QObje QmlBinding::~QmlBinding() { - Q_D(QmlBinding); - if(d->mePtr) - *(d->mePtr) = 0; } void QmlBinding::setTarget(const QmlMetaProperty &prop) @@ -153,12 +150,13 @@ void QmlBinding::setEnabled(bool e) setTrackChange(e); if (e) { - d->mePtr = 0; addToObject(d->property.object()); update(); } else { removeFromObject(); } + + QmlAbstractBinding::setEnabled(e); } int QmlBinding::propertyIndex() @@ -180,13 +178,15 @@ QString QmlBinding::expression() const } QmlAbstractBinding::QmlAbstractBinding() -: m_prevBinding(0), m_nextBinding(0) +: m_mePtr(0), m_prevBinding(0), m_nextBinding(0) { } QmlAbstractBinding::~QmlAbstractBinding() { removeFromObject(); + if (m_mePtr) + *m_mePtr = 0; } void QmlAbstractBinding::addToObject(QObject *object) @@ -217,4 +217,9 @@ QString QmlAbstractBinding::expression() const return QLatin1String(""); } +void QmlAbstractBinding::setEnabled(bool e) +{ + if (e) m_mePtr = 0; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index ad25c16..63b8a15 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -73,7 +73,9 @@ public: private: friend class QmlDeclarativeData; friend class QmlMetaProperty; + friend class QmlVME; + QmlAbstractBinding **m_mePtr; QmlAbstractBinding **m_prevBinding; QmlAbstractBinding *m_nextBinding; }; diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h index 767e6af..963e2c1 100644 --- a/src/declarative/qml/qmlbinding_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -69,8 +69,6 @@ public: bool enabled:1; QmlMetaProperty property; - - QmlAbstractBinding **mePtr; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index a10b1e3..e1f4a90 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -72,6 +72,8 @@ void QmlBinding_Id::setEnabled(bool e) } else { removeFromObject(); } + + QmlAbstractBinding::setEnabled(e); } int QmlBinding_Id::propertyIndex() @@ -147,6 +149,8 @@ void QmlBinding_ObjProperty::setEnabled(bool e) } else { removeFromObject(); } + + QmlAbstractBinding::setEnabled(e); } int QmlBinding_ObjProperty::propertyIndex() diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index fdfeddc..79b1d89 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -541,9 +541,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); bindValues.append(bind); - QmlBindingPrivate *p = - static_cast(QObjectPrivate::get(bind)); - p->mePtr = &bindValues.values[bindValues.count - 1]; + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->addToObject(target); bind->setTarget(mp); @@ -558,7 +556,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData new QmlBinding_Id(target, instr.assignIdOptBinding.property, ctxt, instr.assignIdOptBinding.id); bindValues.append(bind); - // ### Need a mePtr + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->addToObject(target); } break; @@ -573,7 +571,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlCompiledData new QmlBinding_ObjProperty(target, instr.assignObjPropBinding.property, context, instr.assignObjPropBinding.contextIdx, instr.assignObjPropBinding.notifyIdx); bindValues.append(bind); - // ### Need a mePtr + bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->addToObject(target); } break; -- cgit v0.12