Optimize signal handling
authorAaron Kennedy <aaron.kennedy@nokia.com>
Mon, 10 Oct 2011 03:52:34 +0000 (13:52 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 11 Oct 2011 23:31:11 +0000 (01:31 +0200)
Bindings connect to lots of signals that are never emitted.  By managing
signal connection lists ourselves, we can do a much better job than Qt's
generic signal/slot connection logic.

Also, by connecting to QDeclarativeNotifierEndpoint's rather than QObject
slots, we can eliminate the need to instantiate a QObject for the V4 and
V8 binding managers.

Change-Id: I598667deaefdbd2860227bd74378a1b196761686
Reviewed-on: http://codereview.qt-project.org/6278
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Sanity-Review: Aaron Kennedy <aaron.kennedy@nokia.com>

16 files changed:
src/declarative/qml/qdeclarativebinding.cpp
src/declarative/qml/qdeclarativebinding_p.h
src/declarative/qml/qdeclarativebinding_p_p.h
src/declarative/qml/qdeclarativedata_p.h
src/declarative/qml/qdeclarativeengine.cpp
src/declarative/qml/qdeclarativeexpression.cpp
src/declarative/qml/qdeclarativeexpression.h
src/declarative/qml/qdeclarativeexpression_p.h
src/declarative/qml/qdeclarativenotifier.cpp
src/declarative/qml/qdeclarativenotifier_p.h
src/declarative/qml/qdeclarativeproperty.cpp
src/declarative/qml/qdeclarativeproperty_p.h
src/declarative/qml/v4/qdeclarativev4bindings.cpp
src/declarative/qml/v4/qdeclarativev4bindings_p.h
src/declarative/qml/v8/qv8bindings.cpp
src/declarative/qml/v8/qv8bindings_p.h

index 9a69a6b..72dceb8 100644 (file)
@@ -412,7 +412,7 @@ void QDeclarativeBindingPrivate::printBindingLoopError(QDeclarativeProperty &pro
     qmlInfo(prop.object()) << QDeclarativeBinding::tr("Binding loop detected for property \"%1\"").arg(prop.name());
 }
 
-void QDeclarativeBindingPrivate::emitValueChanged()
+void QDeclarativeBindingPrivate::expressionChanged()
 {
     Q_Q(QDeclarativeBinding);
     q->update();
index fedd636..fc9dd87 100644 (file)
@@ -178,7 +178,7 @@ public Q_SLOTS:
 
 protected:
     ~QDeclarativeBinding();
-    void emitValueChanged();
+    void expressionChanged();
 
 private:
     Q_DECLARE_PRIVATE(QDeclarativeBinding)
index dc7ec07..78c4e0e 100644 (file)
@@ -67,7 +67,7 @@ public:
     QDeclarativeBindingPrivate();
     ~QDeclarativeBindingPrivate();
 
-    virtual void emitValueChanged();
+    virtual void expressionChanged();
 
     static void printBindingLoopError(QDeclarativeProperty &prop);
 
index b987ffd..3229c5e 100644 (file)
@@ -68,6 +68,7 @@ class QDeclarativePropertyCache;
 class QDeclarativeContextData;
 class QDeclarativeNotifier;
 class QDeclarativeDataExtended;
+class QDeclarativeNotifierEndpoint;
 // This class is structured in such a way, that simply zero'ing it is the
 // default state for elemental object allocations.  This is crucial in the
 // workings of the QDeclarativeInstruction::CreateSimpleObject instruction.
@@ -77,22 +78,24 @@ class Q_DECLARATIVE_EXPORT QDeclarativeData : public QAbstractDeclarativeData
 public:
     QDeclarativeData()
         : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), 
-          hasTaintedV8Object(false), context(0), outerContext(0), bindings(0), nextContextObject(0), 
-          prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), 
-          deferredComponent(0), deferredIdx(0), v8objectid(0), propertyCache(0), guards(0), 
-          extendedData(0) {
+          hasTaintedV8Object(false), notifyList(0), context(0), outerContext(0), bindings(0), 
+          nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), 
+          lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), v8objectid(0), 
+          propertyCache(0), guards(0), extendedData(0) {
           init(); 
-      }
+    }
 
     static inline void init() {
         QAbstractDeclarativeData::destroyed = destroyed;
         QAbstractDeclarativeData::parentChanged = parentChanged;
         QAbstractDeclarativeData::objectNameChanged = objectNameChanged;
+        QAbstractDeclarativeData::signalEmitted = signalEmitted;
     }
 
     static void destroyed(QAbstractDeclarativeData *, QObject *);
     static void parentChanged(QAbstractDeclarativeData *, QObject *, QObject *);
     static void objectNameChanged(QAbstractDeclarativeData *, QObject *);
+    static void signalEmitted(QAbstractDeclarativeData *, QObject *, int, void **);
 
     void destroyed(QObject *);
     void parentChanged(QObject *, QObject *);
@@ -109,6 +112,23 @@ public:
     quint32 hasTaintedV8Object:1;
     quint32 dummy:27;
 
+    struct NotifyList {
+        quint64 connectionMask;
+
+        quint16 maximumTodoIndex;
+        quint16 notifiesSize;
+
+        QDeclarativeNotifierEndpoint *todo;
+        QDeclarativeNotifierEndpoint**notifies;
+        void layout();
+    private:
+        void layout(QDeclarativeNotifierEndpoint*);
+    };
+    NotifyList *notifyList;
+    
+    inline QDeclarativeNotifierEndpoint *notify(int index);
+    void addNotify(int index, QDeclarativeNotifierEndpoint *);
+
     // The context that created the C++ object
     QDeclarativeContextData *context; 
     // The outermost context in which this object lives
@@ -163,6 +183,25 @@ private:
     mutable QDeclarativeDataExtended *extendedData;
 };
 
+QDeclarativeNotifierEndpoint *QDeclarativeData::notify(int index)
+{
+    Q_ASSERT(index <= 0xFFFF);
+
+    if (!notifyList || !(notifyList->connectionMask & (1 << (index % 64)))) {
+        return 0;
+    } else if (index < notifyList->notifiesSize) {
+        return notifyList->notifies[index];
+    } else if (index <= notifyList->maximumTodoIndex) {
+        notifyList->layout();
+    }
+
+    if (index < notifyList->notifiesSize) {
+        return notifyList->notifies[index];
+    } else {
+        return 0;
+    }
+}
+
 QT_END_NAMESPACE
 
 #endif // QDECLARATIVEDATA_P_H
index 5231704..383d37a 100644 (file)
@@ -410,6 +410,15 @@ void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o
     static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
 }
 
+void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
+{
+    QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+    if (!ddata) return; // Probably being deleted
+
+    QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
+    if (ep) QDeclarativeNotifier::emitNotify(ep);
+}
+
 void QDeclarativeEnginePrivate::init()
 {
     Q_Q(QDeclarativeEngine);
@@ -1047,6 +1056,80 @@ QDeclarativeDataExtended::~QDeclarativeDataExtended()
 {
 }
 
+void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
+{
+    if (endpoint->next)
+        layout(endpoint->next);
+
+    int index = endpoint->sourceSignal;
+    index = qMin(index, 0xFFFF - 1);
+
+    endpoint->next = notifies[index];
+    if (endpoint->next) endpoint->next->prev = &endpoint->next;
+    endpoint->prev = &notifies[index];
+    notifies[index] = endpoint;
+}
+
+void QDeclarativeData::NotifyList::layout()
+{
+    Q_ASSERT(maximumTodoIndex >= notifiesSize);
+
+    if (todo) {
+        QDeclarativeNotifierEndpoint **old = notifies;
+        const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
+        notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
+        const int memsetSize = (maximumTodoIndex - notifiesSize + 1) * 
+                               sizeof(QDeclarativeNotifierEndpoint*);
+        memset(notifies + notifiesSize, 0, memsetSize);
+
+        if (notifies != old) {
+            for (int ii = 0; ii < notifiesSize; ++ii)
+                if (notifies[ii]) 
+                    notifies[ii]->prev = &notifies[ii];
+        }
+
+        notifiesSize = maximumTodoIndex + 1;
+
+        layout(todo);
+    }
+
+    maximumTodoIndex = 0;
+    todo = 0;
+}
+
+void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
+{
+    if (!notifyList) {
+        notifyList = (NotifyList *)malloc(sizeof(NotifyList));
+        notifyList->connectionMask = 0;
+        notifyList->maximumTodoIndex = 0;
+        notifyList->notifiesSize = 0;
+        notifyList->todo = 0;
+        notifyList->notifies = 0;
+    }
+
+    Q_ASSERT(!endpoint->isConnected());
+
+    index = qMin(index, 0xFFFF - 1);
+    notifyList->connectionMask |= (1 << (index % 64));
+
+    if (index < notifyList->notifiesSize) {
+
+        endpoint->next = notifyList->notifies[index];
+        if (endpoint->next) endpoint->next->prev = &endpoint->next;
+        endpoint->prev = &notifyList->notifies[index];
+        notifyList->notifies[index] = endpoint;
+
+    } else {
+        notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
+
+        endpoint->next = notifyList->todo;
+        if (endpoint->next) endpoint->next->prev = &endpoint->next;
+        endpoint->prev = &notifyList->todo;
+        notifyList->todo = endpoint;
+    }
+}
+
 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
 {
     if (!extendedData) extendedData = new QDeclarativeDataExtended;
@@ -1093,6 +1176,17 @@ void QDeclarativeData::destroyed(QObject *object)
         guard->objectDestroyed(object);
     }
 
+    if (notifyList) {
+        while (notifyList->todo)
+            notifyList->todo->disconnect();
+        for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
+            while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
+                ep->disconnect();
+        }
+        free(notifyList->notifies);
+        free(notifyList);
+    }
+
     if (extendedData)
         delete extendedData;
 
index 4f6a719..c62314d 100644 (file)
@@ -70,7 +70,7 @@ bool QDeclarativeDelayedError::addError(QDeclarativeEnginePrivate *e)
 
 QDeclarativeJavaScriptExpression::QDeclarativeJavaScriptExpression()
 : m_requiresThisObject(0), m_useSharedContext(0), m_notifyOnValueChanged(0), 
-  m_scopeObject(0), m_notifyObject(0), m_notifyIndex(-1)
+  m_scopeObject(0)
 {
 }
 
@@ -183,8 +183,6 @@ QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObje
     \endcode
 */
 
-static int QDeclarativeExpression_notifyIdx = -1;
-
 /*!
     Create an invalid QDeclarativeExpression.
 
@@ -194,11 +192,6 @@ static int QDeclarativeExpression_notifyIdx = -1;
 QDeclarativeExpression::QDeclarativeExpression()
 : QObject(*new QDeclarativeExpressionPrivate, 0)
 {
-    Q_D(QDeclarativeExpression);
-
-    if (QDeclarativeExpression_notifyIdx == -1) 
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*!  \internal */
@@ -210,10 +203,6 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt,
 {
     Q_D(QDeclarativeExpression);
     d->init(ctxt, expr, isRewritten, object, url, lineNumber);
-
-    if (QDeclarativeExpression_notifyIdx == -1) 
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*!
@@ -264,10 +253,6 @@ QDeclarativeExpression::QDeclarativeExpression(const QDeclarativeScriptString &s
 
     if (defaultConstruction)
         d->init(QDeclarativeContextData::get(script.context()), script.script(), script.scopeObject());
-
-    if (QDeclarativeExpression_notifyIdx == -1)
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*!
@@ -285,10 +270,6 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContext *ctxt,
 {
     Q_D(QDeclarativeExpression);
     d->init(QDeclarativeContextData::get(ctxt), expression, scope);
-
-    if (QDeclarativeExpression_notifyIdx == -1) 
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*! 
@@ -300,10 +281,6 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
 {
     Q_D(QDeclarativeExpression);
     d->init(ctxt, expression, scope);
-
-    if (QDeclarativeExpression_notifyIdx == -1) 
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*!  \internal */
@@ -313,10 +290,6 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
 {
     Q_D(QDeclarativeExpression);
     d->init(ctxt, expression, scope);
-
-    if (QDeclarativeExpression_notifyIdx == -1) 
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*!  
@@ -335,11 +308,6 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
 
     Q_D(QDeclarativeExpression);
     d->init(ctxt, function, scope);
-
-    if (QDeclarativeExpression_notifyIdx == -1)
-        QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
-
-    d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
 }
 
 /*!
@@ -436,23 +404,9 @@ void QDeclarativeJavaScriptExpression::resetNotifyOnValueChanged()
     guardList.clear();
 }
 
-void QDeclarativeJavaScriptExpression::setNotifyObject(QObject *object, int index)
-{
-    guardList.clear();
-
-    m_notifyObject = object;
-    m_notifyIndex = index;
-
-    if (!object || index == -1) {
-        m_notifyObject = 0;
-        m_notifyIndex = -1;
-    }
-}
-
 v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::Function> function, bool *isUndefined)
 {
     Q_ASSERT(context() && context()->engine);
-    Q_ASSERT(!notifyOnValueChanged() || (m_notifyObject && m_notifyIndex != -1));
 
     if (function.IsEmpty() || function->IsUndefined()) {
         if (isUndefined) *isUndefined = true;
@@ -518,7 +472,7 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
     }
 
     if (!watcher.wasDeleted() && notifyOnValueChanged()) {
-        guardList.updateGuards(m_notifyObject, m_notifyIndex, this, ep->capturedProperties);
+        guardList.updateGuards(this, ep->capturedProperties);
     }
 
     if (lastCapturedProperties.count())
@@ -531,20 +485,17 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
     return result;
 }
 
-void QDeclarativeJavaScriptExpression::GuardList::updateGuards(QObject *notifyObject, int notifyIndex,
-                                                               QDeclarativeJavaScriptExpression *expression,
-                                                               const CapturedProperties &properties)
+void 
+QDeclarativeJavaScriptExpression::GuardList::updateGuards(QDeclarativeJavaScriptExpression *expression,
+                                                          const CapturedProperties &properties)
 {
-    Q_ASSERT(notifyObject);
-    Q_ASSERT(notifyIndex != -1);
-
     if (properties.count() == 0) {
         clear();
         return;
     }
 
     if (properties.count() != length) {
-        QDeclarativeNotifierEndpoint *newGuardList = new QDeclarativeNotifierEndpoint[properties.count()];
+        Endpoint *newGuardList = new Endpoint[properties.count()];
 
         for (int ii = 0; ii < qMin(length, properties.count()); ++ii) 
            endpoints[ii].copyAndClear(newGuardList[ii]);
@@ -557,11 +508,10 @@ void QDeclarativeJavaScriptExpression::GuardList::updateGuards(QObject *notifyOb
     bool outputWarningHeader = false;
     bool noChanges = true;
     for (int ii = 0; ii < properties.count(); ++ii) {
-        QDeclarativeNotifierEndpoint &guard = endpoints[ii];
+        Endpoint &guard = endpoints[ii];
         const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
 
-        guard.target = notifyObject;
-        guard.targetMethod = notifyIndex;
+        guard.expression = expression;
 
         if (property.notifier != 0) {
 
@@ -802,12 +752,6 @@ QDeclarativeError QDeclarativeExpression::error() const
     return d->error;
 }
 
-/*! \internal */
-void QDeclarativeExpressionPrivate::_q_notify()
-{
-    emitValueChanged();
-}
-
 /*!
     \fn void QDeclarativeExpression::valueChanged()
 
@@ -816,7 +760,7 @@ void QDeclarativeExpressionPrivate::_q_notify()
     calling QDeclarativeExpression::evaluate()) before this signal will be emitted.
 */
 
-void QDeclarativeExpressionPrivate::emitValueChanged()
+void QDeclarativeExpressionPrivate::expressionChanged()
 {
     Q_Q(QDeclarativeExpression);
     emit q->valueChanged();
index edd93a1..ae4884b 100644 (file)
@@ -106,7 +106,6 @@ private:
 
     Q_DISABLE_COPY(QDeclarativeExpression)
     Q_DECLARE_PRIVATE(QDeclarativeExpression)
-    Q_PRIVATE_SLOT(d_func(), void _q_notify())
     friend class QDeclarativeDebugger;
     friend class QDeclarativeContext;
     friend class QDeclarativeVME;
index 9feea5c..4e31efb 100644 (file)
@@ -147,11 +147,12 @@ public:
 
     void setNotifyOnValueChanged(bool v);
     void resetNotifyOnValueChanged();
-    void setNotifyObject(QObject *, int );
 
     inline QObject *scopeObject() const;
     inline void setScopeObject(QObject *v);
 
+    virtual void expressionChanged() {}
+
 protected:
     inline virtual QString expressionIdentifier();
 
@@ -162,8 +163,6 @@ private:
     quint32 m_dummy:29;
 
     QObject *m_scopeObject;
-    QObject *m_notifyObject;
-    int m_notifyIndex;
 
     class GuardList {
     public:
@@ -172,11 +171,18 @@ private:
         void inline clear();
 
         typedef QPODVector<QDeclarativeEnginePrivate::CapturedProperty> CapturedProperties;
-        void updateGuards(QObject *guardObject, int guardObjectNotifyIndex,
-                          QDeclarativeJavaScriptExpression *, const CapturedProperties &properties);
+        void updateGuards(QDeclarativeJavaScriptExpression *, const CapturedProperties &properties);
 
     private:
-        QDeclarativeNotifierEndpoint *endpoints;
+        struct Endpoint : public QDeclarativeNotifierEndpoint {
+            Endpoint() : expression(0) { callback = &endpointCallback; }
+            static void endpointCallback(QDeclarativeNotifierEndpoint *e) { 
+                static_cast<Endpoint *>(e)->expression->expressionChanged(); 
+            }
+            QDeclarativeJavaScriptExpression *expression;
+        };
+
+        Endpoint *endpoints;
         int length;
     };
     GuardList guardList;
@@ -203,7 +209,7 @@ public:
     static inline QDeclarativeExpression *get(QDeclarativeExpressionPrivate *expr);
 
     void _q_notify();
-    virtual void emitValueChanged();
+    virtual void expressionChanged();
 
     static void exceptionToError(v8::Handle<v8::Message>, QDeclarativeError &);
     static v8::Persistent<v8::Function> evalFunction(QDeclarativeContextData *ctxt, QObject *scope, 
index 33a1660..77bce8e 100644 (file)
@@ -46,22 +46,20 @@ QT_BEGIN_NAMESPACE
 
 void QDeclarativeNotifier::emitNotify(QDeclarativeNotifierEndpoint *endpoint)
 {
-    QDeclarativeNotifierEndpoint::Notifier *n = endpoint->asNotifier();
+    QDeclarativeNotifierEndpoint **oldDisconnected = endpoint->disconnected;
+    endpoint->disconnected = &endpoint;
 
-    QDeclarativeNotifierEndpoint **oldDisconnected = n->disconnected;
-    n->disconnected = &endpoint;
-
-    if (n->next)
-        emitNotify(n->next);
+    if (endpoint->next)
+        emitNotify(endpoint->next);
 
     if (endpoint) {
         void *args[] = { 0 };
 
-        QMetaObject::metacall(endpoint->target, QMetaObject::InvokeMetaMethod, 
-                              endpoint->targetMethod, args);
+        Q_ASSERT(endpoint->callback);
+        endpoint->callback(endpoint);
 
-        if (endpoint)
-            endpoint->asNotifier()->disconnected = oldDisconnected;
+        if (endpoint) 
+            endpoint->disconnected = oldDisconnected;
     } 
 
     if (oldDisconnected) *oldDisconnected = endpoint;
@@ -69,58 +67,45 @@ void QDeclarativeNotifier::emitNotify(QDeclarativeNotifierEndpoint *endpoint)
 
 void QDeclarativeNotifierEndpoint::connect(QObject *source, int sourceSignal)
 {
-    Signal *s = toSignal();
-    
-    if (s->source == source && s->sourceSignal == sourceSignal)
-        return;
-
     disconnect();
 
-    QDeclarativePropertyPrivate::connect(source, sourceSignal, target, targetMethod);
-
-    s->source = source;
-    s->sourceSignal = sourceSignal;
+    this->source = source;
+    this->sourceSignal = sourceSignal;
+    QDeclarativePropertyPrivate::flushSignal(source, sourceSignal);
+    QDeclarativeData *ddata = QDeclarativeData::get(source, true);
+    ddata->addNotify(sourceSignal, this);
 }
 
 void QDeclarativeNotifierEndpoint::copyAndClear(QDeclarativeNotifierEndpoint &other)
 {
+    if (&other == this)
+        return;
+
     other.disconnect();
 
-    other.target = target;
-    other.targetMethod = targetMethod;
+    other.callback = callback;
 
     if (!isConnected())
         return;
 
-    if (SignalType == type) {
-        Signal *other_s = other.toSignal();
-        Signal *s = asSignal();
-
-        other_s->source = s->source;
-        other_s->sourceSignal = s->sourceSignal;
-        s->source = 0;
-    } else if(NotifierType == type) {
-        Notifier *other_n = other.toNotifier();
-        Notifier *n = asNotifier();
-
-        other_n->notifier = n->notifier;
-        other_n->disconnected = n->disconnected;
-        if (other_n->disconnected) *other_n->disconnected = &other;
-
-        if (n->next) {
-            other_n->next = n->next;
-            n->next->asNotifier()->prev = &other_n->next;
-        }
-        other_n->prev = n->prev;
-        *other_n->prev = &other;
-
-        n->prev = 0;
-        n->next = 0;
-        n->disconnected = 0;
-        n->notifier = 0;
-    } 
+    other.notifier = notifier;
+    other.sourceSignal = sourceSignal;
+    other.disconnected = disconnected;
+    if (other.disconnected) *other.disconnected = &other;
+
+    if (next) {
+        other.next = next;
+        next->prev = &other.next;
+    }
+    other.prev = prev;
+    *other.prev = &other;
+
+    prev = 0;
+    next = 0;
+    disconnected = 0;
+    notifier = 0;
+    sourceSignal = -1;
 }
 
-
 QT_END_NAMESPACE
 
index 6974ea2..d9c334a 100644 (file)
@@ -42,6 +42,7 @@
 #ifndef QDECLARATIVENOTIFIER_P_H
 #define QDECLARATIVENOTIFIER_P_H
 
+#include "private/qdeclarativedata_p.h"
 #include "private/qdeclarativeguard_p.h"
 
 QT_BEGIN_NAMESPACE
@@ -55,6 +56,7 @@ public:
     inline void notify();
 
 private:
+    friend class QDeclarativeData;
     friend class QDeclarativeNotifierEndpoint;
 
     static void emitNotify(QDeclarativeNotifierEndpoint *);
@@ -65,11 +67,10 @@ class QDeclarativeNotifierEndpoint
 {
 public:
     inline QDeclarativeNotifierEndpoint();
-    inline QDeclarativeNotifierEndpoint(QObject *t, int m);
     inline ~QDeclarativeNotifierEndpoint();
 
-    QObject *target;
-    int targetMethod;
+    typedef void (*Callback)(QDeclarativeNotifierEndpoint *);
+    Callback callback;
 
     inline bool isConnected();
     inline bool isConnected(QObject *source, int sourceSignal);
@@ -82,38 +83,17 @@ public:
     void copyAndClear(QDeclarativeNotifierEndpoint &other);
 
 private:
+    friend class QDeclarativeData;
     friend class QDeclarativeNotifier;
 
-    struct Signal {
-        QDeclarativeGuard<QObject> source;
-        int sourceSignal;
-    };
-
-    struct Notifier {
-        QDeclarativeNotifier *notifier;
-        QDeclarativeNotifierEndpoint **disconnected;
-
-        QDeclarativeNotifierEndpoint  *next;
-        QDeclarativeNotifierEndpoint **prev;
-    };
-
-    enum { InvalidType, SignalType, NotifierType } type;
     union {
-        struct {
-            Signal *signal;
-            union {
-                char signalData[sizeof(Signal)];
-                qint64 q_for_alignment_1;
-                double q_for_alignment_2;
-            };
-        };
-        Notifier notifier;
+        QDeclarativeNotifier *notifier;
+        QObject *source;
     };
-
-    inline Notifier *toNotifier();
-    inline Notifier *asNotifier();
-    inline Signal *toSignal();
-    inline Signal *asSignal();
+    int sourceSignal;
+    QDeclarativeNotifierEndpoint **disconnected;
+    QDeclarativeNotifierEndpoint  *next;
+    QDeclarativeNotifierEndpoint **prev;
 };
 
 QDeclarativeNotifier::QDeclarativeNotifier()
@@ -125,12 +105,13 @@ QDeclarativeNotifier::~QDeclarativeNotifier()
 {    
     QDeclarativeNotifierEndpoint *endpoint = endpoints;
     while (endpoint) {
-        QDeclarativeNotifierEndpoint::Notifier *n = endpoint->asNotifier();
+        QDeclarativeNotifierEndpoint *n = endpoint;
         endpoint = n->next;
 
         n->next = 0;
         n->prev = 0;
         n->notifier = 0;
+        n->sourceSignal = -1;
         if (n->disconnected) *n->disconnected = 0;
         n->disconnected = 0;
     }
@@ -143,123 +124,51 @@ void QDeclarativeNotifier::notify()
 }
 
 QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint()
-: target(0), targetMethod(0), type(InvalidType) 
-{
-}
-
-QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint(QObject *t, int m)
-: target(t), targetMethod(m), type(InvalidType) 
+: callback(0), notifier(0), sourceSignal(-1), disconnected(0), next(0), prev(0)
 {
 }
 
 QDeclarativeNotifierEndpoint::~QDeclarativeNotifierEndpoint()
 {
     disconnect();
-    if (SignalType == type) {
-        Signal *s = asSignal();
-        s->~Signal();
-    }
 }
 
 bool QDeclarativeNotifierEndpoint::isConnected()
 {
-    if (SignalType == type) {
-        return asSignal()->source;
-    } else if (NotifierType == type) {
-        return asNotifier()->notifier;
-    } else {
-        return false;
-    }
+    return prev != 0;
 }
 
 bool QDeclarativeNotifierEndpoint::isConnected(QObject *source, int sourceSignal)
 {
-    return SignalType == type && asSignal()->source == source && asSignal()->sourceSignal == sourceSignal;
+    return sourceSignal != -1 && this->source == source && this->sourceSignal == sourceSignal;
 }
 
 bool QDeclarativeNotifierEndpoint::isConnected(QDeclarativeNotifier *notifier)
 {
-    return NotifierType == type && asNotifier()->notifier == notifier;
+    return sourceSignal == -1 && this->notifier == notifier;
 }
 
 void QDeclarativeNotifierEndpoint::connect(QDeclarativeNotifier *notifier)
 {
-    Notifier *n = toNotifier();
-    
-    if (n->notifier == notifier)
-        return;
-
     disconnect();
 
-    n->next = notifier->endpoints;
-    if (n->next) { n->next->asNotifier()->prev = &n->next; }
+    next = notifier->endpoints;
+    if (next) { next->prev = &next; }
     notifier->endpoints = this;
-    n->prev = &notifier->endpoints;
-    n->notifier = notifier;
+    prev = &notifier->endpoints;
+    this->notifier = notifier;
 }
 
 void QDeclarativeNotifierEndpoint::disconnect()
 {
-    if (type == SignalType) {
-        Signal *s = asSignal();
-        if (s->source) {
-            QMetaObject::disconnectOne(s->source, s->sourceSignal, target, targetMethod);
-            s->source = 0;
-        }
-    } else if (type == NotifierType) {
-        Notifier *n = asNotifier();
-
-        if (n->next) n->next->asNotifier()->prev = n->prev;
-        if (n->prev) *n->prev = n->next;
-        if (n->disconnected) *n->disconnected = 0;
-        n->next = 0;
-        n->prev = 0;
-        n->disconnected = 0;
-        n->notifier = 0;
-    }
-}
-
-QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::toNotifier()
-{
-    if (NotifierType == type) 
-        return asNotifier();
-
-    if (SignalType == type) {
-        disconnect();
-        Signal *s = asSignal();
-        s->~Signal();
-    }
-
-    type = NotifierType;
-    Notifier *n = asNotifier();
-    n->next = 0;
-    n->prev = 0;
-    n->disconnected = 0;
-    n->notifier = 0;
-    return n;
-}
-
-QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::asNotifier() 
-{ 
-    Q_ASSERT(type == NotifierType);
-    return &notifier;
-}
-
-QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::toSignal()
-{
-    if (SignalType == type) 
-        return asSignal();
-
-    disconnect();
-    signal = new (&signalData) Signal;
-    type = SignalType;
-    return signal;
-}
-
-QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::asSignal() 
-{ 
-    Q_ASSERT(type == SignalType);
-    return signal;
+    if (next) next->prev = prev;
+    if (prev) *prev = next;
+    if (disconnected) *disconnected = 0;
+    next = 0;
+    prev = 0;
+    disconnected = 0;
+    notifier = 0;
+    sourceSignal = -1;
 }
 
 QT_END_NAMESPACE
index 78c37de..d95b13c 100644 (file)
@@ -1777,6 +1777,11 @@ bool QDeclarativePropertyPrivate::connect(const QObject *sender, int signal_inde
     return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);
 }
 
+void QDeclarativePropertyPrivate::flushSignal(const QObject *sender, int signal_index)
+{
+    flush_vme_signal(sender, signal_index);
+}
+
 /*!
 Return \a metaObject's [super] meta object that provides data for \a property.
 */
index 190cf2a..f8ecef1 100644 (file)
@@ -147,6 +147,7 @@ public:
                         const QObject *receiver, int method_index,
                         int type = 0, int *types = 0);
     static const QMetaObject *metaObjectForProperty(const QMetaObject *, int);
+    static void flushSignal(const QObject *sender, int signal_index);
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyPrivate::WriteFlags)
index 7aa5496..df2ce7b 100644 (file)
@@ -187,92 +187,18 @@ void Register::init(Type type)
 
 } // end of anonymous namespace
 
-class QDeclarativeV4BindingsPrivate : public QObjectPrivate
-{
-    Q_DECLARE_PUBLIC(QDeclarativeV4Bindings)
-
-public:
-    QDeclarativeV4BindingsPrivate();
-    virtual ~QDeclarativeV4BindingsPrivate();
-
-    struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError {
-        Binding() : enabled(false), updating(0), property(0),
-                    scope(0), target(0), executedBlocks(0), parent(0) {}
-
-        // Inherited from QDeclarativeAbstractBinding
-        virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
-        virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
-        virtual void destroy();
-
-        int index:30;
-        bool enabled:1;
-        bool updating:1;
-        int property;
-        QObject *scope;
-        QObject *target;
-        quint32 executedBlocks;
-
-        QDeclarativeV4BindingsPrivate *parent;
-    };
-
-    typedef QDeclarativeNotifierEndpoint Subscription;
-    Subscription *subscriptions;
-
-    void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);
-
-    QDeclarativeV4Program *program;
-    QDeclarativeRefCount *dataRef;
-    Binding *bindings;
-
-    static int methodCount;
-
-    void init();
-    void run(int instr, quint32 &executedBlocks, QDeclarativeContextData *context,
-             QDeclarativeDelayedError *error, QObject *scope, QObject *output, 
-             QDeclarativePropertyPrivate::WriteFlags storeFlags
-#ifdef QML_THREADED_INTERPRETER
-             , void ***decode_instr = 0
-#endif
-             );
-
-
-    inline void unsubscribe(int subIndex);
-    inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
-    inline void subscribe(QObject *o, int notifyIndex, int subIndex);
-
-    inline static qint32 toInt32(qreal n);
-    static const qreal D32;
-    static quint32 toUint32(qreal n);
-};
-
-QDeclarativeV4BindingsPrivate::QDeclarativeV4BindingsPrivate()
+QDeclarativeV4Bindings::QDeclarativeV4Bindings(const char *programData, 
+                                               QDeclarativeContextData *context, 
+                                               QDeclarativeRefCount *ref)
 : subscriptions(0), program(0), dataRef(0), bindings(0)
 {
-}
-
-QDeclarativeV4BindingsPrivate::~QDeclarativeV4BindingsPrivate()
-{
-    delete [] subscriptions; subscriptions = 0;
-    if (dataRef) dataRef->release();
-}
-
-int QDeclarativeV4BindingsPrivate::methodCount = -1;
-
-QDeclarativeV4Bindings::QDeclarativeV4Bindings(const char *program, QDeclarativeContextData *context, 
-                                               QDeclarativeRefCount *dataRef)
-: QObject(*(new QDeclarativeV4BindingsPrivate))
-{
-    Q_D(QDeclarativeV4Bindings);
-
-    if (d->methodCount == -1)
-        d->methodCount = QDeclarativeV4Bindings::staticMetaObject.methodCount();
-
-    d->program = (QDeclarativeV4Program *)program;
-    d->dataRef = dataRef;
+    program = (QDeclarativeV4Program *)programData;
+    dataRef = ref;
     if (dataRef) dataRef->addref();
 
     if (program) {
-        d->init();
+        subscriptions = new Subscription[program->subscriptions];
+        bindings = new Binding[program->bindings];
 
         QDeclarativeAbstractExpression::setContext(context);
     }
@@ -280,30 +206,28 @@ QDeclarativeV4Bindings::QDeclarativeV4Bindings(const char *program, QDeclarative
 
 QDeclarativeV4Bindings::~QDeclarativeV4Bindings()
 {
-    Q_D(QDeclarativeV4Bindings);
-
-    delete [] d->bindings;
+    delete [] bindings;
+    delete [] subscriptions; subscriptions = 0;
+    if (dataRef) dataRef->release();
 }
 
 QDeclarativeAbstractBinding *QDeclarativeV4Bindings::configBinding(int index, QObject *target, 
-                                                        QObject *scope, int property)
+                                                                   QObject *scope, int property)
 {
-    Q_D(QDeclarativeV4Bindings);
-
-    QDeclarativeV4BindingsPrivate::Binding *rv = d->bindings + index;
+    Binding *rv = bindings + index;
 
     rv->index = index;
     rv->property = property;
     rv->target = target;
     rv->scope = scope;
-    rv->parent = d;
+    rv->parent = this;
 
     addref(); // This is decremented in Binding::destroy()
 
     return rv;
 }
 
-void QDeclarativeV4BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
+void QDeclarativeV4Bindings::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
 {
     if (enabled != e) {
         enabled = e;
@@ -312,50 +236,47 @@ void QDeclarativeV4BindingsPrivate::Binding::setEnabled(bool e, QDeclarativeProp
     }
 }
 
-void QDeclarativeV4BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
+void QDeclarativeV4Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
 {
     QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding);
     parent->run(this, flags);
     QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding);
 }
 
-void QDeclarativeV4BindingsPrivate::Binding::destroy()
+void QDeclarativeV4Bindings::Binding::destroy()
 {
     enabled = false;
     removeFromObject();
     clear();
     removeError();
-    parent->q_func()->release();
+    parent->release();
 }
 
-int QDeclarativeV4Bindings::qt_metacall(QMetaObject::Call c, int id, void **)
+void QDeclarativeV4Bindings::Subscription::subscriptionCallback(QDeclarativeNotifierEndpoint *e) 
 {
-    Q_D(QDeclarativeV4Bindings);
-
-    if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) {
-        id -= d->methodCount;
+    Subscription *s = static_cast<Subscription *>(e);
+    s->bindings->subscriptionNotify(s->method);
+}
 
-        QDeclarativeV4Program::BindingReferenceList *list = d->program->signalTable(id);
+void QDeclarativeV4Bindings::subscriptionNotify(int id)
+{
+    QDeclarativeV4Program::BindingReferenceList *list = program->signalTable(id);
 
-        for (quint32 ii = 0; ii < list->count; ++ii) {
-            QDeclarativeV4Program::BindingReference *bindingRef = list->bindings + ii;
+    for (quint32 ii = 0; ii < list->count; ++ii) {
+        QDeclarativeV4Program::BindingReference *bindingRef = list->bindings + ii;
 
-            QDeclarativeV4BindingsPrivate::Binding *binding = d->bindings + bindingRef->binding;
-            if (binding->executedBlocks & bindingRef->blockMask)
-                d->run(binding, QDeclarativePropertyPrivate::DontRemoveBinding);
-        }
+        Binding *binding = bindings + bindingRef->binding;
+        if (binding->executedBlocks & bindingRef->blockMask)
+            run(binding, QDeclarativePropertyPrivate::DontRemoveBinding);
     }
-    return -1;
 }
 
-void QDeclarativeV4BindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
+void QDeclarativeV4Bindings::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
 {
-    Q_Q(QDeclarativeV4Bindings);
-
     if (!binding->enabled)
         return;
 
-    QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context();
+    QDeclarativeContextData *context = QDeclarativeAbstractExpression::context();
     if (!context || !context->isValid()) 
         return;
 
@@ -373,7 +294,7 @@ void QDeclarativeV4BindingsPrivate::run(Binding *binding, QDeclarativePropertyPr
         } else {
             name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
         }
-        qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeV4Bindings", "Binding loop detected for property \"%1\"").arg(name);
+        qmlInfo(binding->target) << tr("Binding loop detected for property \"%1\"").arg(name);
         return;
     }
 
@@ -396,33 +317,29 @@ void QDeclarativeV4BindingsPrivate::run(Binding *binding, QDeclarativePropertyPr
 }
 
 
-void QDeclarativeV4BindingsPrivate::unsubscribe(int subIndex)
+void QDeclarativeV4Bindings::unsubscribe(int subIndex)
 {
-    QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex);
+    Subscription *sub = (subscriptions + subIndex);
     sub->disconnect();
 }
 
-void QDeclarativeV4BindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex)
+void QDeclarativeV4Bindings::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex)
 {
-    Q_Q(QDeclarativeV4Bindings);
-
     unsubscribe(subIndex);
 
     if (p->idValues[idIndex]) {
-        QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex);
-        sub->target = q;
-        sub->targetMethod = methodCount + subIndex;
+        Subscription *sub = (subscriptions + subIndex);
+        sub->bindings = this;
+        sub->method = subIndex;
         sub->connect(&p->idValues[idIndex].bindings);
     }
 }
  
-void QDeclarativeV4BindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex)
+void QDeclarativeV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
 {
-    Q_Q(QDeclarativeV4Bindings);
-
-    QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex);
-    sub->target = q;
-    sub->targetMethod = methodCount + subIndex; 
+    Subscription *sub = (subscriptions + subIndex);
+    sub->bindings = this;
+    sub->method = subIndex; 
     if (o)
         sub->connect(o, notifyIndex);
     else
@@ -507,14 +424,6 @@ inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *conte
         return base;
 }
 
-void QDeclarativeV4BindingsPrivate::init()
-{
-    if (program->subscriptions)
-        subscriptions = new QDeclarativeV4BindingsPrivate::Subscription[program->subscriptions];
-
-    bindings = new QDeclarativeV4BindingsPrivate::Binding[program->bindings];
-}
-
 static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
 {
     QVariant qtscript = qtscriptRaw;
@@ -680,9 +589,9 @@ static void throwException(int id, QDeclarativeDelayedError *error,
         QDeclarativeEnginePrivate::warning(context->engine, error->error);
 }
 
-const qreal QDeclarativeV4BindingsPrivate::D32 = 4294967296.0;
+const qreal QDeclarativeV4Bindings::D32 = 4294967296.0;
 
-qint32 QDeclarativeV4BindingsPrivate::toInt32(qreal n)
+qint32 QDeclarativeV4Bindings::toInt32(qreal n)
 {
     if (qIsNaN(n) || qIsInf(n) || (n == 0))
         return 0;
@@ -702,7 +611,7 @@ qint32 QDeclarativeV4BindingsPrivate::toInt32(qreal n)
     return qint32 (n);
 }
 
-inline quint32 QDeclarativeV4BindingsPrivate::toUint32(qreal n)
+inline quint32 QDeclarativeV4Bindings::toUint32(qreal n)
 {
     if (qIsNaN(n) || qIsInf(n) || (n == 0))
         return 0;
@@ -751,25 +660,24 @@ void **QDeclarativeV4Bindings::getDecodeInstrTable()
     if (!decode_instr) {
         QDeclarativeV4Bindings *dummy = new QDeclarativeV4Bindings(0, 0, 0);
         quint32 executedBlocks = 0;
-        dummy->d_func()->run(0, executedBlocks, 0, 0, 0, 0, 
-                             QDeclarativePropertyPrivate::BypassInterceptor, 
-                             &decode_instr);
+        dummy->run(0, executedBlocks, 0, 0, 0, 0, 
+                   QDeclarativePropertyPrivate::BypassInterceptor, 
+                   &decode_instr);
         dummy->release();
     }
     return decode_instr;
 }
 #endif
 
-void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
-                                        QDeclarativeContextData *context, QDeclarativeDelayedError *error,
-                                        QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags
+void QDeclarativeV4Bindings::run(int instrIndex, quint32 &executedBlocks,
+                                 QDeclarativeContextData *context, QDeclarativeDelayedError *error,
+                                 QObject *scope, QObject *output, 
+                                 QDeclarativePropertyPrivate::WriteFlags storeFlags
 #ifdef QML_THREADED_INTERPRETER
-                                        ,void ***table
+                                 ,void ***table
 #endif
-                                        )
+                                 )
 {
-    Q_Q(QDeclarativeV4Bindings);
-
 #ifdef QML_THREADED_INTERPRETER
     if (table) {
         static void *decode_instr[] = {
@@ -840,11 +748,11 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
             reg.setUndefined();
         } else {
             int subIdx = instr->fetchAndSubscribe.subscription;
-            QDeclarativeV4BindingsPrivate::Subscription *sub = 0;
+            Subscription *sub = 0;
             if (subIdx != -1) {
                 sub = (subscriptions + subIdx);
-                sub->target = q;
-                sub->targetMethod = methodCount + subIdx;
+                sub->bindings = this;
+                sub->method = subIdx;
             }
             reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
             if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
index c0345ea..d69d75b 100644 (file)
@@ -61,28 +61,82 @@ QT_BEGIN_HEADER
 
 QT_BEGIN_NAMESPACE
 
-class QDeclarativeV4BindingsPrivate;
-class QDeclarativeV4Bindings : public QObject, 
-                               public QDeclarativeAbstractExpression, 
+class QDeclarativeV4Program;
+class QDeclarativeV4Bindings : public QDeclarativeAbstractExpression, 
                                public QDeclarativeRefCount
 {
+    Q_DECLARE_TR_FUNCTIONS(QDeclarativeV4Bindings)
 public:
     QDeclarativeV4Bindings(const char *program, QDeclarativeContextData *context,
                            QDeclarativeRefCount *);
     virtual ~QDeclarativeV4Bindings();
 
-    QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property);
+    QDeclarativeAbstractBinding *configBinding(int index, QObject *target, 
+                                               QObject *scope, int property);
 
 #ifdef QML_THREADED_INTERPRETER
     static void **getDecodeInstrTable();
 #endif
 
-protected:
-    int qt_metacall(QMetaObject::Call, int, void **);
-
 private:
     Q_DISABLE_COPY(QDeclarativeV4Bindings)
-    Q_DECLARE_PRIVATE(QDeclarativeV4Bindings)
+
+    struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError {
+        Binding() : enabled(false), updating(0), property(0),
+                    scope(0), target(0), executedBlocks(0), parent(0) {}
+
+        // Inherited from QDeclarativeAbstractBinding
+        virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
+        virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
+        virtual void destroy();
+
+        int index:30;
+        bool enabled:1;
+        bool updating:1;
+        int property;
+        QObject *scope;
+        QObject *target;
+        quint32 executedBlocks;
+
+        QDeclarativeV4Bindings *parent;
+    };
+
+    struct Subscription : public QDeclarativeNotifierEndpoint
+    {
+        Subscription() : bindings(0), method(-1) { callback = &subscriptionCallback; }
+        static void subscriptionCallback(QDeclarativeNotifierEndpoint *e);
+        QDeclarativeV4Bindings *bindings;
+        int method;
+    };
+    friend class Subscription;
+
+    Subscription *subscriptions;
+
+    void subscriptionNotify(int);
+    void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);
+
+    QDeclarativeV4Program *program;
+    QDeclarativeRefCount *dataRef;
+    Binding *bindings;
+
+    void init();
+    void run(int instr, quint32 &executedBlocks, QDeclarativeContextData *context,
+             QDeclarativeDelayedError *error, QObject *scope, QObject *output, 
+             QDeclarativePropertyPrivate::WriteFlags storeFlags
+#ifdef QML_THREADED_INTERPRETER
+             , void ***decode_instr = 0
+#endif
+             );
+
+
+    inline void unsubscribe(int subIndex);
+    inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
+    inline void subscribe(QObject *o, int notifyIndex, int subIndex);
+
+    inline static qint32 toInt32(qreal n);
+    static const qreal D32;
+    static quint32 toUint32(qreal n);
+
 };
 
 QT_END_NAMESPACE
index 3c98af2..b94cebd 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
-class QV8BindingsPrivate : public QObjectPrivate
-{
-    Q_DECLARE_PUBLIC(QV8Bindings)
-public:
-    QV8BindingsPrivate();
-
-    struct Binding : public QDeclarativeJavaScriptExpression,
-                     public QDeclarativeAbstractBinding {
-        Binding();
-
-        void update() { QDeclarativeAbstractBinding::update(); }
-
-        // Inherited from QDeclarativeJavaScriptExpression
-        inline virtual QString expressionIdentifier();
-
-        // Inherited from QDeclarativeAbstractBinding
-        virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
-        virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
-        virtual void destroy();
-        virtual void refresh();
-
-        int index:30;
-        bool enabled:1;
-        bool updating:1;
-        int line;
-        QDeclarativeProperty property;
-        QV8BindingsPrivate *parent;
-    };
-
-    QUrl url;
-    int bindingsCount;
-    Binding *bindings;
-    v8::Persistent<v8::Array> functions;
-};
-
-QV8BindingsPrivate::QV8BindingsPrivate()
-: bindingsCount(0), bindings(0)
-{
-}
-
-QV8BindingsPrivate::Binding::Binding()
+QV8Bindings::Binding::Binding()
 : index(-1), enabled(false), updating(false), line(-1), parent(0)
 {
 }
 
-void QV8BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
+void QV8Bindings::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
 {
     if (enabled != e) {
         enabled = e;
@@ -105,12 +65,12 @@ void QV8BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate
     }
 }
 
-void QV8BindingsPrivate::Binding::refresh()
+void QV8Bindings::Binding::refresh()
 {
     update();
 }
 
-void QV8BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
+void QV8Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
 {
     if (!enabled)
         return;
@@ -164,27 +124,30 @@ void QV8BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags
     }
 }
 
-QString QV8BindingsPrivate::Binding::expressionIdentifier()
+QString QV8Bindings::Binding::expressionIdentifier()
 {
     return parent->url.toString() + QLatin1String(":") + QString::number(line);
 }
 
-void QV8BindingsPrivate::Binding::destroy()
+void QV8Bindings::Binding::expressionChanged()
+{
+    update(QDeclarativePropertyPrivate::DontRemoveBinding);
+}
+
+void QV8Bindings::Binding::destroy()
 {
     enabled = false;
     removeFromObject();
     clear();
     removeError();
-    parent->q_func()->release();
+    parent->release();
 }
 
 QV8Bindings::QV8Bindings(const QString &program, int index, int line,
                          QDeclarativeCompiledData *compiled, 
                          QDeclarativeContextData *context)
-: QObject(*(new QV8BindingsPrivate))
+: bindingsCount(0), bindings(0)
 {
-    Q_D(QV8Bindings);
-
     QV8Engine *engine = QDeclarativeEnginePrivate::getV8Engine(context->engine);
 
     if (compiled->v8bindings[index].IsEmpty()) {
@@ -198,29 +161,27 @@ QV8Bindings::QV8Bindings(const QString &program, int index, int line,
             compiled->v8bindings[index] = qPersistentNew(v8::Local<v8::Array>::Cast(result));
     }
 
-    d->url = compiled->url;
-    d->functions = qPersistentNew(compiled->v8bindings[index]);
-    d->bindingsCount = d->functions->Length();
-    d->bindings = new QV8BindingsPrivate::Binding[d->bindingsCount];
+    url = compiled->url;
+    functions = qPersistentNew(compiled->v8bindings[index]);
+    bindingsCount = functions->Length();
+    bindings = new QV8Bindings::Binding[bindingsCount];
     
     setContext(context);
 }
 
 QV8Bindings::~QV8Bindings()
 {
-    Q_D(QV8Bindings);
-    qPersistentDispose(d->functions);
+    qPersistentDispose(functions);
 
-    delete [] d->bindings;
-    d->bindings = 0;
-    d->bindingsCount = 0;
+    delete [] bindings;
+    bindings = 0;
+    bindingsCount = 0;
 }
 
 QDeclarativeAbstractBinding *QV8Bindings::configBinding(int index, QObject *target, QObject *scope, 
                                                         const QDeclarativeProperty &property, int line)
 {
-    Q_D(QV8Bindings);
-    QV8BindingsPrivate::Binding *rv = d->bindings + index;
+    QV8Bindings::Binding *rv = bindings + index;
 
     rv->line = line;
     rv->index = index;
@@ -229,23 +190,11 @@ QDeclarativeAbstractBinding *QV8Bindings::configBinding(int index, QObject *targ
     rv->setScopeObject(scope);
     rv->setUseSharedContext(true);
     rv->setNotifyOnValueChanged(true);
-    rv->setNotifyObject(this, index);
-    rv->parent = d;
+    rv->parent = this;
 
     addref(); // This is decremented in Binding::destroy()
 
     return rv;
 }
 
-int QV8Bindings::qt_metacall(QMetaObject::Call c, int id, void **)
-{
-    Q_D(QV8Bindings);
-
-    if (c == QMetaObject::InvokeMetaMethod) {
-        QV8BindingsPrivate::Binding *binding = d->bindings + id;
-        binding->update(QDeclarativePropertyPrivate::DontRemoveBinding);
-    }
-    return -1;
-}
-
 QT_END_NAMESPACE
index b387a50..3b3aed2 100644 (file)
@@ -64,8 +64,7 @@ QT_BEGIN_NAMESPACE
 class QDeclarativeCompiledData;
 
 class QV8BindingsPrivate;
-class QV8Bindings : public QObject, 
-                    public QDeclarativeAbstractExpression, 
+class QV8Bindings : public QDeclarativeAbstractExpression, 
                     public QDeclarativeRefCount
 {
 public:
@@ -77,12 +76,37 @@ public:
     QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope, 
                                                const QDeclarativeProperty &prop, int line);
 
-protected:
-    int qt_metacall(QMetaObject::Call, int, void **);
-
 private:
     Q_DISABLE_COPY(QV8Bindings)
-    Q_DECLARE_PRIVATE(QV8Bindings)
+
+    struct Binding : public QDeclarativeJavaScriptExpression,
+                     public QDeclarativeAbstractBinding {
+        Binding();
+
+        void update() { QDeclarativeAbstractBinding::update(); }
+
+        // Inherited from QDeclarativeJavaScriptExpression
+        inline virtual QString expressionIdentifier();
+        virtual void expressionChanged();
+
+        // Inherited from QDeclarativeAbstractBinding
+        virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
+        virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
+        virtual void destroy();
+        virtual void refresh();
+
+        int index:30;
+        bool enabled:1;
+        bool updating:1;
+        int line;
+        QDeclarativeProperty property;
+        QV8Bindings *parent;
+    };
+
+    QUrl url;
+    int bindingsCount;
+    Binding *bindings;
+    v8::Persistent<v8::Array> functions;
 };
 
 QT_END_NAMESPACE