diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-05-08 11:23:31 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-05-11 21:53:22 -0700 |
commit | cdd0e8fa6772c407f699995d6f1d03434d7f33aa (patch) | |
tree | 6eafbe7423ef905940fedb8729e1c7d2edb0372d | |
parent | 05ebf3e54b7065aa95f03404831bf1bb1cae3d0a (diff) |
QSlotObjectBase: move the `which` parameter to the 4th position
This places the first through third parameters on the exact positions
that they will be used to perform the operations in the switch, saving
the compiler from generating a few instructions to move data around. All
ABIs Qt supports that pass any function parameters in registers at all
pass at least 4.
We keep the return type as void (instead of returning bool, for the
Compare case) so the compiler can apply tail-call optimizations for
those two typical cases.
PMF case: https://gcc.godbolt.org/z/9oP5boKfj
Function case: https://gcc.godbolt.org/z/e9vEzd5dj
Functor case: https://gcc.godbolt.org/z/s8Ejjra7P
Change-Id: I3e3bfef633af4130a03afffd175d3e3009c56323
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qobjectdefs_impl.h | 31 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 4 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 4 |
5 files changed, 43 insertions, 5 deletions
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 61a0fe9ebb..de014a5525 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -268,7 +268,11 @@ template<typename Func, typename Args, typename R> class QPrivateSlotObject : public QSlotObjectBase, private FunctionStorage<Func> { typedef QtPrivate::FunctionPointer<Func> FuncType; +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) +#else + static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret) +#endif { const auto that = static_cast<QPrivateSlotObject*>(this_); switch (which) { diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 33df3624d2..6f2dac783b 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -387,17 +387,17 @@ namespace QtPrivate { // internal base class (interface) containing functions required to call a slot managed by a pointer to function. class QSlotObjectBase { -#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) - QAtomicInt m_ref = 1; -#endif // Don't use virtual functions here; we don't want the // compiler to create tons of per-polymorphic-class stuff that // we'll never need. We just use one function pointer, and the // Operations enum below to distinguish requests +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QAtomicInt m_ref = 1; typedef void (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret); const ImplFn m_impl; - -#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) +#else + using ImplFn = void (*)(QSlotObjectBase* this_, QObject *receiver, void **args, int which, bool *ret); + const ImplFn m_impl; QAtomicInt m_ref = 1; #endif protected: @@ -414,11 +414,24 @@ namespace QtPrivate { explicit QSlotObjectBase(ImplFn fn) : m_impl(fn) {} inline int ref() noexcept { return m_ref.ref(); } +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) inline void destroyIfLastRef() noexcept { if (!m_ref.deref()) m_impl(Destroy, this, nullptr, nullptr, nullptr); } inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, nullptr, a, &ret); return ret; } inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, nullptr); } +#else + inline void destroyIfLastRef() noexcept + { if (!m_ref.deref()) m_impl(this, nullptr, nullptr, Destroy, nullptr); } + + inline bool compare(void **a) + { + bool ret = false; + m_impl(this, nullptr, a, Compare, &ret); + return ret; + } + inline void call(QObject *r, void **a) { m_impl(this, r, a, Call, nullptr); } +#endif bool isImpl(ImplFn f) const { return m_impl == f; } protected: ~QSlotObjectBase() {} @@ -438,7 +451,15 @@ namespace QtPrivate { QtPrivate::FunctionPointer<FunctorValue>, QtPrivate::Functor<FunctorValue, Args::size> >; + +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) Q_DECL_HIDDEN static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) +#else + // Design note: the first three arguments match those for typical Call + // and Destroy uses. We return void to enable tail call optimization + // for those too. + Q_DECL_HIDDEN static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret) +#endif { const auto that = static_cast<QCallableObject*>(this_); switch (which) { diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 765a596585..b6513a0b71 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -2477,8 +2477,13 @@ QPropertyAdaptorSlotObject::QPropertyAdaptorSlotObject(QObject *o, const QMetaPr { } +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) void QPropertyAdaptorSlotObject::impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) +#else +void QPropertyAdaptorSlotObject::impl(QSlotObjectBase *this_, QObject *r, void **a, int which, + bool *ret) +#endif { auto self = static_cast<QPropertyAdaptorSlotObject *>(this_); switch (which) { diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 9096df25ad..5b1d0eb273 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -917,7 +917,11 @@ class QPropertyAdaptorSlotObject : public QUntypedPropertyData, public QSlotObje QObject *obj; QMetaProperty metaProperty_; +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret); +#else + static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret); +#endif QPropertyAdaptorSlotObject(QObject *o, const QMetaProperty& p); diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 16f53d58da..5cb9faf01f 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -6813,7 +6813,11 @@ struct QmlReceiver : public QtPrivate::QSlotObjectBase , magic(0) {} +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) static void impl(int which, QSlotObjectBase *this_, QObject *, void **metaArgs, bool *ret) +#else + static void impl(QSlotObjectBase *this_, QObject *, void **metaArgs, int which, bool *ret) +#endif { switch (which) { case Destroy: delete static_cast<QmlReceiver*>(this_); return; |