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>
This commit is contained in:
parent
05ebf3e54b
commit
cdd0e8fa67
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user