aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-10-10 13:52:34 +1000
committerQt by Nokia <qt-info@nokia.com>2011-10-12 01:31:11 +0200
commit0466acb02740b5dbf3254d6445186b4d3ccd0699 (patch)
treea1b7314c2faae73cf93403afdc7ca92f2106d70d
parent3422d4adda7480a44a063ab86447c2fe2792fe02 (diff)
Optimize signal handling
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>
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp2
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h2
-rw-r--r--src/declarative/qml/qdeclarativebinding_p_p.h2
-rw-r--r--src/declarative/qml/qdeclarativedata_p.h49
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp94
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp74
-rw-r--r--src/declarative/qml/qdeclarativeexpression.h1
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h20
-rw-r--r--src/declarative/qml/qdeclarativenotifier.cpp83
-rw-r--r--src/declarative/qml/qdeclarativenotifier_p.h149
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp5
-rw-r--r--src/declarative/qml/qdeclarativeproperty_p.h1
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings.cpp206
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings_p.h70
-rw-r--r--src/declarative/qml/v8/qv8bindings.cpp97
-rw-r--r--src/declarative/qml/v8/qv8bindings_p.h36
16 files changed, 404 insertions, 487 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 9a69a6bfd0..72dceb80dc 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -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();
diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h
index fedd63634b..fc9dd8758f 100644
--- a/src/declarative/qml/qdeclarativebinding_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p.h
@@ -178,7 +178,7 @@ public Q_SLOTS:
protected:
~QDeclarativeBinding();
- void emitValueChanged();
+ void expressionChanged();
private:
Q_DECLARE_PRIVATE(QDeclarativeBinding)
diff --git a/src/declarative/qml/qdeclarativebinding_p_p.h b/src/declarative/qml/qdeclarativebinding_p_p.h
index dc7ec074c8..78c4e0e829 100644
--- a/src/declarative/qml/qdeclarativebinding_p_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p_p.h
@@ -67,7 +67,7 @@ public:
QDeclarativeBindingPrivate();
~QDeclarativeBindingPrivate();
- virtual void emitValueChanged();
+ virtual void expressionChanged();
static void printBindingLoopError(QDeclarativeProperty &prop);
diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h
index b987ffd6ea..3229c5e878 100644
--- a/src/declarative/qml/qdeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedata_p.h
@@ -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
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 5231704da9..383d37a3ed 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -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;
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index 4f6a71911f..c62314d94b 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -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();
diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h
index edd93a1240..ae4884ba82 100644
--- a/src/declarative/qml/qdeclarativeexpression.h
+++ b/src/declarative/qml/qdeclarativeexpression.h
@@ -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;
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 9feea5ca22..4e31efb806 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -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,
diff --git a/src/declarative/qml/qdeclarativenotifier.cpp b/src/declarative/qml/qdeclarativenotifier.cpp
index 33a1660c46..77bce8e440 100644
--- a/src/declarative/qml/qdeclarativenotifier.cpp
+++ b/src/declarative/qml/qdeclarativenotifier.cpp
@@ -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
diff --git a/src/declarative/qml/qdeclarativenotifier_p.h b/src/declarative/qml/qdeclarativenotifier_p.h
index 6974ea2eed..d9c334a4c1 100644
--- a/src/declarative/qml/qdeclarativenotifier_p.h
+++ b/src/declarative/qml/qdeclarativenotifier_p.h
@@ -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
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index 78c37deff4..d95b13cda9 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -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.
*/
diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h
index 190cf2a694..f8ecef1e02 100644
--- a/src/declarative/qml/qdeclarativeproperty_p.h
+++ b/src/declarative/qml/qdeclarativeproperty_p.h
@@ -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)
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
index 7aa5496403..df2ce7bf00 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
@@ -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)
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings_p.h b/src/declarative/qml/v4/qdeclarativev4bindings_p.h
index c0345ea3c4..d69d75b835 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings_p.h
+++ b/src/declarative/qml/v4/qdeclarativev4bindings_p.h
@@ -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
diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp
index 3c98af2951..b94cebdf03 100644
--- a/src/declarative/qml/v8/qv8bindings.cpp
+++ b/src/declarative/qml/v8/qv8bindings.cpp
@@ -51,52 +51,12 @@
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
diff --git a/src/declarative/qml/v8/qv8bindings_p.h b/src/declarative/qml/v8/qv8bindings_p.h
index b387a50df3..3b3aed269b 100644
--- a/src/declarative/qml/v8/qv8bindings_p.h
+++ b/src/declarative/qml/v8/qv8bindings_p.h
@@ -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