From 2410be7f45b8688c9910336ec9b8a79d3232b9c7 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 5 Apr 2016 16:44:51 +0200 Subject: Tune fast-exit for signal activation for QML. When using QML, it quite often happens that only the QML engine is connected to a signal, and no C++ handlers. By splitting up the fast-exit case and handling QML separately, we can prevent a call to QThread::currentThreadId, and locking+unlocking the mutex. On x86 this saves ~130 instructions according to valgrind. Change-Id: I947fe42afe351922339ac982a6d498bc2f7b5192 Reviewed-by: Simon Hausmann Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 17 ++++++++++------- src/corelib/kernel/qobject_p.h | 14 ++++++++++---- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 2b0eff3708..04ec713522 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3609,18 +3609,21 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i { int signal_index = signalOffset + local_signal_index; - if (!sender->d_func()->isSignalConnected(signal_index) - && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback) { - return; // nothing connected to these signals, and no spy - } - if (sender->d_func()->blockSig) return; - if (sender->d_func()->declarativeData && QAbstractDeclarativeData::signalEmitted) + if (sender->d_func()->isDeclarativeSignalConnected(signal_index) + && QAbstractDeclarativeData::signalEmitted) { QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender, signal_index, argv); + } + + if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false) + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { + // The possible declarative connection is done, and nothing else is connected, so: + return; + } void *empty_argv[] = { 0 }; if (qt_signal_spy_callback_set.signal_begin_callback != 0) { diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index e6ab75f104..4383ece245 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -199,7 +199,8 @@ public: } int signalIndex(const char *signalName, const QMetaObject **meta = 0) const; - inline bool isSignalConnected(uint signalIdx) const; + inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const; + inline bool isDeclarativeSignalConnected(uint signalIdx) const; // To allow abitrary objects to call connectNotify()/disconnectNotify() without making // the API public in QObject. This is used by QQmlNotifierEndpoint. @@ -250,12 +251,17 @@ public: \a signal_index must be the index returned by QObjectPrivate::signalIndex; */ -inline bool QObjectPrivate::isSignalConnected(uint signal_index) const +inline bool QObjectPrivate::isSignalConnected(uint signal_index, bool checkDeclarative) const { return signal_index >= sizeof(connectedSignals) * 8 || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) - || (declarativeData && QAbstractDeclarativeData::isSignalConnected - && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index))); + || (checkDeclarative && isDeclarativeSignalConnected(signal_index))); +} + +inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const +{ + return declarativeData && QAbstractDeclarativeData::isSignalConnected + && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index); } inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, -- cgit v1.2.3