diff options
-rw-r--r-- | src/declarative/qml/qml.pri | 6 | ||||
-rw-r--r-- | src/declarative/qml/qmlbindingoptimizations.cpp | 173 | ||||
-rw-r--r-- | src/declarative/qml/qmlbindingvme_p.h | 182 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiledbindings.cpp (renamed from src/declarative/qml/qmlbindingvme.cpp) | 400 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiledbindings_p.h (renamed from src/declarative/qml/qmlbindingoptimizations_p.h) | 69 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext.cpp | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 62 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 4 |
9 files changed, 415 insertions, 489 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 9268545..6f2f57f 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -32,9 +32,8 @@ SOURCES += \ $$PWD/qmlscriptparser.cpp \ $$PWD/qmlenginedebug.cpp \ $$PWD/qmlrewrite.cpp \ - $$PWD/qmlbindingvme.cpp \ $$PWD/qmlvaluetype.cpp \ - $$PWD/qmlbindingoptimizations.cpp \ + $$PWD/qmlcompiledbindings.cpp \ $$PWD/qmlxmlhttprequest.cpp \ $$PWD/qmlsqldatabase.cpp \ $$PWD/qmetaobjectbuilder.cpp \ @@ -95,13 +94,12 @@ HEADERS += \ $$PWD/qmldeclarativedata_p.h \ $$PWD/qmlerror.h \ $$PWD/qmlscriptparser_p.h \ - $$PWD/qmlbindingvme_p.h \ $$PWD/qmlenginedebug_p.h \ $$PWD/qmlrewrite_p.h \ $$PWD/qpodvector_p.h \ $$PWD/qbitfield_p.h \ $$PWD/qmlvaluetype_p.h \ - $$PWD/qmlbindingoptimizations_p.h \ + $$PWD/qmlcompiledbindings_p.h \ $$PWD/qmlxmlhttprequest_p.h \ $$PWD/qmlsqldatabase_p.h \ $$PWD/qmetaobjectbuilder_p.h \ diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp deleted file mode 100644 index 1e49636..0000000 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmlbindingoptimizations_p.h" - -#include "qmlcontext_p.h" -#include <QtDeclarative/qmlinfo.h> -#include "qmlbindingvme_p.h" - -QT_BEGIN_NAMESPACE - -int QmlOptimizedBindings::methodCount = -1; - -QmlOptimizedBindings::QmlOptimizedBindings(const char *program, QmlContext *context) -: m_program(program) -{ - if (methodCount == -1) - methodCount = QmlOptimizedBindings::staticMetaObject.methodCount(); - - m_config.target = this; - m_config.targetSlot = metaObject()->methodCount(); - - quint32 bindings = 0; - QmlBindingVME::init(m_program, &m_config, &m_signalTable, &bindings); - - m_bindings = new Binding[bindings]; - - QmlAbstractExpression::setContext(context); -} - -QmlOptimizedBindings::~QmlOptimizedBindings() -{ - delete [] m_bindings; -} - -QmlAbstractBinding *QmlOptimizedBindings::configBinding(int index, QObject *target, - QObject *scope, int property) -{ - Binding *rv = m_bindings + index; - - rv->index = index; - rv->property = property; - rv->target = target; - rv->scope = scope; - rv->parent = this; - - addref(); // This is decremented in Binding::destroy() - - return rv; -} - -void QmlOptimizedBindings::Binding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) -{ - if (e) { - addToObject(target); - update(flags); - } else { - removeFromObject(); - } - - QmlAbstractBinding::setEnabled(e, flags); - - if (enabled != e) { - enabled = e; - - if (e) update(flags); - } -} - -int QmlOptimizedBindings::Binding::propertyIndex() -{ - return property & 0xFFFF; -} - -void QmlOptimizedBindings::Binding::update(QmlMetaProperty::WriteFlags) -{ - parent->run(this); -} - -void QmlOptimizedBindings::Binding::destroy() -{ - enabled = false; - removeFromObject(); - parent->release(); -} - -int QmlOptimizedBindings::qt_metacall(QMetaObject::Call c, int id, void **) -{ - if (c == QMetaObject::InvokeMetaMethod && id >= methodCount) { - id -= methodCount; - - quint32 *reeval = m_signalTable + m_signalTable[id]; - quint32 count = *reeval; - ++reeval; - for (quint32 ii = 0; ii < count; ++ii) { - run(m_bindings + reeval[ii]); - } - } - return -1; -} - -void QmlOptimizedBindings::run(Binding *binding) -{ - if (!binding->enabled) - return; - if (binding->updating) - qWarning("ERROR: Circular binding"); - - QmlContext *context = QmlAbstractExpression::context(); - if (!context) { - qWarning("QmlOptimizedBindings: Attempted to evaluate an expression in an invalid context"); - return; - } - QmlContextPrivate *cp = QmlContextPrivate::get(context); - - if (binding->property & 0xFFFF0000) { - QmlEnginePrivate *ep = QmlEnginePrivate::get(cp->engine); - - QmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; - Q_ASSERT(vt); - vt->read(binding->target, binding->property & 0xFFFF); - - QObject *target = vt; - QmlBindingVME::run(m_program, binding->index, &m_config, cp, binding, - binding->scope, target); - - vt->write(binding->target, binding->property & 0xFFFF, - QmlMetaProperty::DontRemoveBinding); - } else { - QmlBindingVME::run(m_program, binding->index, &m_config, cp, binding, - binding->scope, binding->target); - } -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingvme_p.h b/src/declarative/qml/qmlbindingvme_p.h deleted file mode 100644 index 01280f0..0000000 --- a/src/declarative/qml/qmlbindingvme_p.h +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLBINDINGVME_P_H -#define QMLBINDINGVME_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 <QtCore/qglobal.h> -#include <private/qscriptdeclarativeclass_p.h> -#include "qmlexpression_p.h" -#include "qmlguard_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QObject; -class QmlContextPrivate; -class QmlBindingVME -{ -public: - struct Config { - Config() : target(0), targetSlot(-1), subscriptions(0), identifiers(0) {} - ~Config() { delete [] subscriptions; delete [] identifiers; } - QObject *target; - int targetSlot; - - struct Subscription { - struct Signal { - QmlGuard<QObject> source; - int notifyIndex; - }; - - struct Id { - inline Id(); - inline ~Id(); - inline void reset(); - Id *next; - Id**prev; - QObject *target; - int methodIndex; - }; - - enum { InvalidType, SignalType, IdType } type; - inline Subscription(); - inline ~Subscription(); - bool isSignal() const { return type == SignalType; } - bool isId() const { return type == IdType; } - inline Signal *signal(); - inline Id *id(); - union { - char signalData[sizeof(Signal)]; - char idData[sizeof(Id)]; - }; - }; - Subscription *subscriptions; - QScriptDeclarativeClass::PersistentIdentifier *identifiers; - }; - - static void init(const char *program, Config *config, - quint32 **sigTable, quint32 *bindingCount); - static void run(const char *program, int instr, - Config *config, QmlContextPrivate *context, QmlDelayedError *error, - QObject *scope, QObject *output); - static void dump(const char *); -}; - -QmlBindingVME::Config::Subscription::Subscription() -: type(InvalidType) -{ -} - -QmlBindingVME::Config::Subscription::~Subscription() -{ - if (type == SignalType) ((Signal *)signalData)->~Signal(); - else if (type == IdType) ((Id *)idData)->~Id(); -} - -QmlBindingVME::Config::Subscription::Id::Id() -: next(0), prev(0), target(0), methodIndex(-1) -{ -} - -QmlBindingVME::Config::Subscription::Id::~Id() -{ - reset(); -} - -void QmlBindingVME::Config::Subscription::Id::reset() -{ - if (next) next->prev = prev; - if (prev) *prev = next; - next = 0; - prev = 0; - target = 0; - methodIndex = -1; -} - -class QmlBindingCompilerPrivate; -class QmlBindingCompiler -{ -public: - QmlBindingCompiler(); - ~QmlBindingCompiler(); - - // Returns true if bindings were compiled - bool isValid() const; - - struct Expression - { - QmlParser::Object *component; - QmlParser::Object *context; - QmlParser::Property *property; - QmlParser::Variant expression; - QHash<QString, QmlParser::Object *> ids; - QmlEnginePrivate::Imports imports; - }; - - // -1 on failure, otherwise the binding index to use - int compile(const Expression &, QmlEnginePrivate *); - - // Returns the compiled program - QByteArray program() const; - -private: - QmlBindingCompilerPrivate *d; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QMLBINDINGVME_P_H - diff --git a/src/declarative/qml/qmlbindingvme.cpp b/src/declarative/qml/qmlcompiledbindings.cpp index 47f02b2..d09f7eb 100644 --- a/src/declarative/qml/qmlbindingvme.cpp +++ b/src/declarative/qml/qmlcompiledbindings.cpp @@ -39,7 +39,9 @@ ** ****************************************************************************/ -#include "qmlbindingvme_p.h" +#include "qmlcompiledbindings_p.h" + +#include <QtDeclarative/qmlinfo.h> #include <private/qmlcontext_p.h> #include <private/qmljsast_p.h> #include <private/qmljsengine_p.h> @@ -52,22 +54,6 @@ QT_BEGIN_NAMESPACE using namespace QmlJS; -QmlBindingVME::Config::Subscription::Signal *QmlBindingVME::Config::Subscription::signal() -{ - if (type == IdType) ((Id *)idData)->~Id(); - if (type != SignalType) new (signalData) Signal; - type = SignalType; - return (Signal *)signalData; -} - -QmlBindingVME::Config::Subscription::Id *QmlBindingVME::Config::Subscription::id() -{ - if (type == SignalType) ((Signal *)signalData)->~Signal(); - if (type != IdType) new (idData) Id; - type = IdType; - return (Id *)idData; -} - namespace { // Supported types: int, qreal, QString (needs constr/destr), QObject*, bool struct Register { @@ -106,7 +92,258 @@ struct Register { int type; // Optional type void *data[2]; // Object stored here }; +} + +class QmlCompiledBindingsPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlCompiledBindings) + +public: + QmlCompiledBindingsPrivate(); + virtual ~QmlCompiledBindingsPrivate(); + + struct Binding : public QmlAbstractBinding, public QmlDelayedError { + Binding() : enabled(false), updating(0), property(0), + scope(0), target(0), parent(0) {} + + // Inherited from QmlAbstractBinding + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); + virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); + virtual void destroy(); + + int index:30; + bool enabled:1; + bool updating:1; + int property; + QObject *scope; + QObject *target; + + QmlCompiledBindingsPrivate *parent; + }; + + struct Subscription { + struct Signal { + QmlGuard<QObject> source; + int notifyIndex; + }; + + enum { InvalidType, SignalType, IdType } type; + inline Subscription(); + inline ~Subscription(); + bool isSignal() const { return type == SignalType; } + bool isId() const { return type == IdType; } + inline Signal *signal(); + inline QmlContextPrivate::IdNotifier *id(); + union { + char signalData[sizeof(Signal)]; + char idData[sizeof(QmlContextPrivate::IdNotifier)]; + }; + }; + Subscription *subscriptions; + QScriptDeclarativeClass::PersistentIdentifier *identifiers; + + void run(Binding *); + + const char *programData; + Binding *m_bindings; + quint32 *m_signalTable; + + static int methodCount; + + void init(); + void run(int instr, QmlContextPrivate *context, + QmlDelayedError *error, QObject *scope, QObject *output); + + + inline void unsubscribe(int subIndex); + inline void subscribeId(QmlContextPrivate *p, int idIndex, int subIndex); + inline void subscribe(QObject *o, int notifyIndex, int subIndex); + + QmlPropertyCache::Data *findproperty(QObject *obj, + const QScriptDeclarativeClass::Identifier &name, + QmlEnginePrivate *enginePriv, + QmlPropertyCache::Data &local); + bool findproperty(QObject *obj, + Register *output, + QmlEnginePrivate *enginePriv, + int subIdx, + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal); + void findgeneric(Register *output, // value output + int subIdx, // Subscription index in config + QmlContextPrivate *context, // Context to search in + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal); +}; + +QmlCompiledBindingsPrivate::QmlCompiledBindingsPrivate() +: subscriptions(0), identifiers(0) +{ +} + +QmlCompiledBindingsPrivate::~QmlCompiledBindingsPrivate() +{ + delete [] subscriptions; subscriptions = 0; + delete [] identifiers; identifiers = 0; +} + +QmlCompiledBindingsPrivate::Subscription::Subscription() +: type(InvalidType) +{ +} + +QmlCompiledBindingsPrivate::Subscription::~Subscription() +{ + if (type == SignalType) ((Signal *)signalData)->~Signal(); + else if (type == IdType) ((QmlContextPrivate::IdNotifier *)idData)->~IdNotifier(); +} + + +int QmlCompiledBindingsPrivate::methodCount = -1; + +QmlCompiledBindings::QmlCompiledBindings(const char *program, QmlContext *context) +: QObject(*(new QmlCompiledBindingsPrivate)) +{ + Q_D(QmlCompiledBindings); + + if (d->methodCount == -1) + d->methodCount = QmlCompiledBindings::staticMetaObject.methodCount(); + + d->programData = program; + + d->init(); + + QmlAbstractExpression::setContext(context); +} + +QmlCompiledBindings::~QmlCompiledBindings() +{ + Q_D(QmlCompiledBindings); + + delete [] d->m_bindings; +} + +QmlAbstractBinding *QmlCompiledBindings::configBinding(int index, QObject *target, + QObject *scope, int property) +{ + Q_D(QmlCompiledBindings); + + QmlCompiledBindingsPrivate::Binding *rv = d->m_bindings + index; + + rv->index = index; + rv->property = property; + rv->target = target; + rv->scope = scope; + rv->parent = d; + + addref(); // This is decremented in Binding::destroy() + + return rv; +} + +void QmlCompiledBindingsPrivate::Binding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) +{ + if (e) { + addToObject(target); + update(flags); + } else { + removeFromObject(); + } + QmlAbstractBinding::setEnabled(e, flags); + + if (enabled != e) { + enabled = e; + + if (e) update(flags); + } +} + +int QmlCompiledBindingsPrivate::Binding::propertyIndex() +{ + return property & 0xFFFF; +} + +void QmlCompiledBindingsPrivate::Binding::update(QmlMetaProperty::WriteFlags) +{ + parent->run(this); +} + +void QmlCompiledBindingsPrivate::Binding::destroy() +{ + enabled = false; + removeFromObject(); + parent->q_func()->release(); +} + +int QmlCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **) +{ + Q_D(QmlCompiledBindings); + + if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) { + id -= d->methodCount; + + quint32 *reeval = d->m_signalTable + d->m_signalTable[id]; + quint32 count = *reeval; + ++reeval; + for (quint32 ii = 0; ii < count; ++ii) { + d->run(d->m_bindings + reeval[ii]); + } + } + return -1; +} + +void QmlCompiledBindingsPrivate::run(Binding *binding) +{ + Q_Q(QmlCompiledBindings); + + if (!binding->enabled) + return; + if (binding->updating) + qWarning("ERROR: Circular binding"); + + QmlContext *context = q->QmlAbstractExpression::context(); + if (!context) { + qWarning("QmlCompiledBindings: Attempted to evaluate an expression in an invalid context"); + return; + } + QmlContextPrivate *cp = QmlContextPrivate::get(context); + + if (binding->property & 0xFFFF0000) { + QmlEnginePrivate *ep = QmlEnginePrivate::get(cp->engine); + + QmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF]; + Q_ASSERT(vt); + vt->read(binding->target, binding->property & 0xFFFF); + + QObject *target = vt; + run(binding->index, cp, binding, binding->scope, target); + + vt->write(binding->target, binding->property & 0xFFFF, + QmlMetaProperty::DontRemoveBinding); + } else { + run(binding->index, cp, binding, binding->scope, binding->target); + } +} + +QmlCompiledBindingsPrivate::Subscription::Signal *QmlCompiledBindingsPrivate::Subscription::signal() +{ + if (type == IdType) ((QmlContextPrivate::IdNotifier *)idData)->~IdNotifier(); + if (type != SignalType) new (signalData) Signal; + type = SignalType; + return (Signal *)signalData; +} + +QmlContextPrivate::IdNotifier *QmlCompiledBindingsPrivate::Subscription::id() +{ + if (type == SignalType) ((Signal *)signalData)->~Signal(); + if (type != IdType) new (idData) QmlContextPrivate::IdNotifier; + type = IdType; + return (QmlContextPrivate::IdNotifier *)idData; +} + +namespace { // This structure is exactly 8-bytes in size struct Instr { enum { @@ -411,68 +648,72 @@ struct QmlBindingCompilerPrivate QByteArray buildExceptionData() const; }; -inline void unsubscribe(int subIndex, QmlBindingVME::Config *config) +void QmlCompiledBindingsPrivate::unsubscribe(int subIndex) { - QmlBindingVME::Config::Subscription *sub = (config->subscriptions + subIndex); + Q_Q(QmlCompiledBindings); + + QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); if (sub->isSignal()) { - QmlBindingVME::Config::Subscription::Signal *s = sub->signal(); + QmlCompiledBindingsPrivate::Subscription::Signal *s = sub->signal(); if (s->source) #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) QMetaObject::disconnectOne(s->source, s->notifyIndex, - config->target, config->targetSlot + subIndex); + q, methodCount + subIndex); #else // QTBUG-6781 QMetaObject::disconnect(s->source, s->notifyIndex, - config->target, config->targetSlot + subIndex); + q, methodCount + subIndex); #endif } else if (sub->isId()) { - sub->id()->reset(); + sub->id()->clear(); } } -inline void subscribeId(QmlContextPrivate *p, int idIndex, - int subIndex, QmlBindingVME::Config *config) +void QmlCompiledBindingsPrivate::subscribeId(QmlContextPrivate *p, int idIndex, int subIndex) { - unsubscribe(subIndex, config); + Q_Q(QmlCompiledBindings); + + unsubscribe(subIndex); if (p->idValues[idIndex]) { - QmlBindingVME::Config::Subscription *sub = (config->subscriptions + subIndex); - QmlBindingVME::Config::Subscription::Id *i = sub->id(); + QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); + QmlContextPrivate::IdNotifier *i = sub->id(); i->next = p->idValues[idIndex].bindings; i->prev = &p->idValues[idIndex].bindings; p->idValues[idIndex].bindings = i; if (i->next) i->next->prev = &i->next; - i->target = config->target; - i->methodIndex = config->targetSlot + subIndex; + i->target = q; + i->methodIndex = methodCount + subIndex; } } -inline void subscribe(QObject *o, int notifyIndex, - int subIndex, QmlBindingVME::Config *config) +void QmlCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex) { - QmlBindingVME::Config::Subscription *sub = (config->subscriptions + subIndex); + Q_Q(QmlCompiledBindings); + + QmlCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex); if (sub->isId()) - unsubscribe(subIndex, config); + unsubscribe(subIndex); - QmlBindingVME::Config::Subscription::Signal *s = sub->signal(); + QmlCompiledBindingsPrivate::Subscription::Signal *s = sub->signal(); if (o != s->source || notifyIndex != s->notifyIndex) { if (s->source) #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2)) QMetaObject::disconnectOne(s->source, s->notifyIndex, - config->target, config->targetSlot + subIndex); + q, methodCount + subIndex); #else // QTBUG-6781 QMetaObject::disconnect(s->source, s->notifyIndex, - config->target, config->targetSlot + subIndex); + q, methodCount + subIndex); #endif s->source = o; s->notifyIndex = notifyIndex; if (s->source && s->notifyIndex != -1) - QMetaObject::connect(s->source, s->notifyIndex, config->target, - config->targetSlot + subIndex, Qt::DirectConnection); + QMetaObject::connect(s->source, s->notifyIndex, q, + methodCount + subIndex, Qt::DirectConnection); } } @@ -566,10 +807,11 @@ static QObject *variantToQObject(const QVariant &value, bool *ok) } } -static QmlPropertyCache::Data *findproperty(QObject *obj, - const QScriptDeclarativeClass::Identifier &name, - QmlEnginePrivate *enginePriv, - QmlPropertyCache::Data &local) +QmlPropertyCache::Data * +QmlCompiledBindingsPrivate::findproperty(QObject *obj, + const QScriptDeclarativeClass::Identifier &name, + QmlEnginePrivate *enginePriv, + QmlPropertyCache::Data &local) { QmlPropertyCache *cache = 0; QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); @@ -595,11 +837,10 @@ static QmlPropertyCache::Data *findproperty(QObject *obj, return property; } -static bool findproperty(QObject *obj, Register *output, - QmlEnginePrivate *enginePriv, - QmlBindingVME::Config *config, int subIdx, - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) +bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, + QmlEnginePrivate *enginePriv, + int subIdx, const QScriptDeclarativeClass::Identifier &name, + bool isTerminal) { if (!obj) { output->setUndefined(); @@ -611,7 +852,7 @@ static bool findproperty(QObject *obj, Register *output, if (property) { if (subIdx != -1) - subscribe(obj, property->notifyIndex, subIdx, config); + subscribe(obj, property->notifyIndex, subIdx); if (property->flags & QmlPropertyCache::Data::IsQObjectDerived) { void *args[] = { output->typeDataPtr(), 0 }; @@ -668,12 +909,11 @@ static bool findproperty(QObject *obj, Register *output, } } -static void findgeneric(Register *output, // value output - QmlBindingVME::Config *config, - int subIdx, // Subscription index in config - QmlContextPrivate *context, // Context to search in - const QScriptDeclarativeClass::Identifier &name, - bool isTerminal) +void QmlCompiledBindingsPrivate::findgeneric(Register *output, + int subIdx, + QmlContextPrivate *context, + const QScriptDeclarativeClass::Identifier &name, + bool isTerminal) { QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(context->engine); @@ -685,8 +925,7 @@ static void findgeneric(Register *output, // val if (contextPropertyIndex != -1) { if (subIdx != -1) - subscribe(QmlContextPrivate::get(context), contextPropertyIndex + context->notifyIndex, - subIdx, config); + subscribe(QmlContextPrivate::get(context), contextPropertyIndex + context->notifyIndex, subIdx); if (contextPropertyIndex < context->idValueCount) { output->setQObject(context->idValues[contextPropertyIndex]); @@ -717,7 +956,7 @@ static void findgeneric(Register *output, // val if (QObject *root = context->defaultObjects.isEmpty()?0:context->defaultObjects.first()) { - if (findproperty(root, output, enginePriv, config, subIdx, name, isTerminal)) + if (findproperty(root, output, enginePriv, subIdx, name, isTerminal)) return; } @@ -732,20 +971,16 @@ static void findgeneric(Register *output, // val output->setUndefined(); } -/*! -Returns the signal/binding table. -*/ -void QmlBindingVME::init(const char *programData, Config *config, - quint32 **sigTable, quint32 *bindingCount) +void QmlCompiledBindingsPrivate::init() { Program *program = (Program *)programData; if (program->subscriptions) - config->subscriptions = new Config::Subscription[program->subscriptions]; + subscriptions = new QmlCompiledBindingsPrivate::Subscription[program->subscriptions]; if (program->identifiers) - config->identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers]; + identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers]; - *sigTable = (quint32 *)(program->data() + program->signalTableOffset); - *bindingCount = program->bindings; + m_signalTable = (quint32 *)(program->data() + program->signalTableOffset); + m_bindings = new QmlCompiledBindingsPrivate::Binding[program->bindings]; } static void throwException(int id, QmlDelayedError *error, @@ -769,9 +1004,9 @@ static void throwException(int id, QmlDelayedError *error, qWarning() << error->error; } -void QmlBindingVME::run(const char *programData, int instrIndex, - Config *config, QmlContextPrivate *context, QmlDelayedError *error, - QObject *scope, QObject *output) +void QmlCompiledBindingsPrivate::run(int instrIndex, + QmlContextPrivate *context, QmlDelayedError *error, + QObject *scope, QObject *output) { error->removeError(); @@ -791,17 +1026,15 @@ void QmlBindingVME::run(const char *programData, int instrIndex, break; case Instr::SubscribeId: - subscribeId(context, instr->subscribe.index, instr->subscribe.offset, config); + subscribeId(context, instr->subscribe.index, instr->subscribe.offset); break; case Instr::Subscribe: { QObject *o = 0; - int notifyIndex = instr->subscribe.index; - const Register &object = registers[instr->subscribe.reg]; if (!object.isUndefined()) o = object.getQObject(); - subscribe(o, instr->subscribe.index, instr->subscribe.offset, config); + subscribe(o, instr->subscribe.index, instr->subscribe.offset); } break; @@ -1084,14 +1317,13 @@ void QmlBindingVME::run(const char *programData, int instrIndex, return; case Instr::InitString: - if (!config->identifiers[instr->initstring.offset].identifier) { + if (!identifiers[instr->initstring.offset].identifier) { quint32 len = *(quint32 *)(data + instr->initstring.dataIdx); QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32)); QString str = QString::fromRawData(strdata, len); - config->identifiers[instr->initstring.offset] = - engine->objectClass->createPersistentIdentifier(str); + identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str); } break; @@ -1100,9 +1332,9 @@ void QmlBindingVME::run(const char *programData, int instrIndex, // We start the search in the parent context, as we know that the // name is not present in the current context or it would have been // found during the static compile - findgeneric(registers + instr->find.reg, config, instr->find.subscribeIndex, + findgeneric(registers + instr->find.reg, instr->find.subscribeIndex, QmlContextPrivate::get(context->parent), - config->identifiers[instr->find.name].identifier, + identifiers[instr->find.name].identifier, instr->common.type == Instr::FindGenericTerminal); break; @@ -1116,8 +1348,8 @@ void QmlBindingVME::run(const char *programData, int instrIndex, } findproperty(object.getQObject(), registers + instr->find.reg, - QmlEnginePrivate::get(context->engine), config, - instr->find.subscribeIndex, config->identifiers[instr->find.name].identifier, + QmlEnginePrivate::get(context->engine), + instr->find.subscribeIndex, identifiers[instr->find.name].identifier, instr->common.type == Instr::FindPropertyTerminal); } break; @@ -1186,9 +1418,9 @@ void QmlBindingVME::run(const char *programData, int instrIndex, } } -void QmlBindingVME::dump(const char *programData) +void QmlBindingCompiler::dump(const QByteArray &programData) { - const Program *program = (const Program *)programData; + const Program *program = (const Program *)programData.constData(); qWarning() << "Program.bindings:" << program->bindings; qWarning() << "Program.dataLength:" << program->dataLength; @@ -2513,5 +2745,5 @@ QByteArray QmlBindingCompiler::program() const } -QT_END_NAMESPACE +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlcompiledbindings_p.h index 42b7d17..1d8fac4 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlcompiledbindings_p.h @@ -55,50 +55,57 @@ #include "qmlexpression_p.h" #include "qmlbinding.h" -#include "qmlbindingvme_p.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QmlOptimizedBindings : public QObject, public QmlAbstractExpression, public QmlRefCount +class QmlBindingCompilerPrivate; +class QmlBindingCompiler { public: - QmlOptimizedBindings(const char *program, QmlContext *context); - virtual ~QmlOptimizedBindings(); + QmlBindingCompiler(); + ~QmlBindingCompiler(); + + // Returns true if bindings were compiled + bool isValid() const; + + struct Expression + { + QmlParser::Object *component; + QmlParser::Object *context; + QmlParser::Property *property; + QmlParser::Variant expression; + QHash<QString, QmlParser::Object *> ids; + QmlEnginePrivate::Imports imports; + }; + + // -1 on failure, otherwise the binding index to use + int compile(const Expression &, QmlEnginePrivate *); + + // Returns the compiled program + QByteArray program() const; + + static void dump(const QByteArray &); +private: + QmlBindingCompilerPrivate *d; +}; + +class QmlCompiledBindingsPrivate; +class QmlCompiledBindings : public QObject, public QmlAbstractExpression, public QmlRefCount +{ +public: + QmlCompiledBindings(const char *program, QmlContext *context); + virtual ~QmlCompiledBindings(); + QmlAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property); protected: int qt_metacall(QMetaObject::Call, int, void **); private: - struct Binding : public QmlAbstractBinding, public QmlDelayedError { - Binding() : enabled(false), updating(0), property(0), - scope(0), target(0), parent(0) {} - - // Inherited from QmlAbstractBinding - virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); - virtual int propertyIndex(); - virtual void update(QmlMetaProperty::WriteFlags flags); - virtual void destroy(); - - int index:30; - bool enabled:1; - bool updating:1; - int property; - QObject *scope; - QObject *target; - - QmlOptimizedBindings *parent; - }; - void run(Binding *); - - QmlBindingVME::Config m_config; - const char *m_program; - Binding *m_bindings; - quint32 *m_signalTable; - - static int methodCount; + Q_DISABLE_COPY(QmlCompiledBindings); + Q_DECLARE_PRIVATE(QmlCompiledBindings); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 5937734..2e18b85 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -64,7 +64,7 @@ #include "qmlglobal_p.h" #include "qmlscriptparser_p.h" #include "qmlbinding.h" -#include "qmlbindingvme_p.h" +#include "qmlcompiledbindings_p.h" #include <qfxperf_p_p.h> @@ -2672,7 +2672,7 @@ bool QmlCompiler::completeComponentBuild() if (bindingCompiler.isValid()) { compileState.compiledBindingData = bindingCompiler.program(); - QmlBindingVME::dump(compileState.compiledBindingData); + QmlBindingCompiler::dump(compileState.compiledBindingData); } saveComponentState(); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index f97f142..0eb497d 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -45,7 +45,7 @@ #include "qmlexpression_p.h" #include "qmlengine_p.h" #include "qmlengine.h" -#include "qmlbindingoptimizations_p.h" +#include "qmlcompiledbindings_p.h" #include "qmlinfo.h" #include <qscriptengine.h> @@ -108,7 +108,7 @@ void QmlContextPrivate::destroyed(ContextGuard *guard) while(guard->bindings) { QObject *o = guard->bindings->target; int mi = guard->bindings->methodIndex; - guard->bindings->reset(); + guard->bindings->clear(); if (o) o->qt_metacall(QMetaObject::InvokeMetaMethod, mi, 0); } diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index ffb4298..cd7e1b6 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -59,7 +59,6 @@ #include "qmlengine_p.h" #include "qmlintegercache_p.h" #include "qmltypenamecache_p.h" -#include "qmlbindingvme_p.h" #include <QtCore/qhash.h> #include <QtScript/qscriptvalue.h> @@ -77,7 +76,7 @@ class QmlExpression; class QmlExpressionPrivate; class QmlAbstractExpression; class QmlBinding_Id; -class QmlOptimizedBindings; +class QmlCompiledBindings; class Q_DECLARATIVE_EXPORT QmlContextPrivate : public QObjectPrivate { @@ -114,15 +113,27 @@ public: QmlDeclarativeData *contextObjects; + struct IdNotifier + { + inline IdNotifier(); + inline ~IdNotifier(); + + inline void clear(); + + IdNotifier *next; + IdNotifier**prev; + QObject *target; + int methodIndex; + }; + struct ContextGuard : public QmlGuard<QObject> { - ContextGuard() : priv(0), bindings(0) {} + inline ContextGuard(); + inline ContextGuard &operator=(QObject *obj); + inline virtual void objectDestroyed(QObject *); + QmlContextPrivate *priv; - QmlBindingVME::Config::Subscription::Id *bindings; - ContextGuard &operator=(QObject *obj) { - (QmlGuard<QObject>&)*this = obj; return *this; - } - void objectDestroyed(QObject *) { priv->destroyed(this); } + IdNotifier *bindings; }; ContextGuard *idValues; int idValueCount; @@ -137,12 +148,45 @@ public: return static_cast<QmlContext *>(context->q_func()); } - QmlOptimizedBindings *optimizedBindings; + QmlCompiledBindings *optimizedBindings; // Only used for debugging QList<QPointer<QObject> > instances; }; +QmlContextPrivate::IdNotifier::IdNotifier() +: next(0), prev(0), target(0), methodIndex(-1) +{ +} + +QmlContextPrivate::IdNotifier::~IdNotifier() +{ + clear(); +} + +void QmlContextPrivate::IdNotifier::clear() +{ + if (next) next->prev = prev; + if (prev) *prev = next; + next = 0; prev = 0; target = 0; + methodIndex = -1; +} + +QmlContextPrivate::ContextGuard::ContextGuard() +: priv(0), bindings(0) +{ +} + +QmlContextPrivate::ContextGuard &QmlContextPrivate::ContextGuard::operator=(QObject *obj) +{ + (QmlGuard<QObject>&)*this = obj; return *this; +} + +void QmlContextPrivate::ContextGuard::objectDestroyed(QObject *) +{ + priv->destroyed(this); +} + QT_END_NAMESPACE #endif // QMLCONTEXT_P_H diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 6b2e7af..e9a0449 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -57,7 +57,7 @@ #include "qmlvmemetaobject_p.h" #include "qmlbinding_p.h" #include "qmlcontext_p.h" -#include "qmlbindingoptimizations_p.h" +#include "qmlcompiledbindings_p.h" #include "qmlglobal_p.h" #include "qmlscriptstring.h" @@ -173,7 +173,7 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt, if (instr.init.contextCache != -1) cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); if (instr.init.compiledBinding != -1) - cp->optimizedBindings = new QmlOptimizedBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); + cp->optimizedBindings = new QmlCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); } break; |