aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpyside/pyside.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2024-05-17 14:43:13 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2024-05-21 09:57:01 +0200
commit985d9e01a2d52cecfb5083941e819969033d1061 (patch)
treeb8665c87fcc188eeaa4bb06a5ffc4db4c27f15a3 /sources/pyside6/libpyside/pyside.cpp
parent84939474074974b080474a224e5e2900cad25d8a (diff)
LazyInit: Speed up QObject conversion
Lazy loading introduced a performance regression for applications using for example an event filter on QApplication, where all internal QObject-derived types from QML occur. This triggered the lazy loading mechanism for each of those classes that have no binding. To fix this, introduce checks to typeName(const QObject *) that skip the internal classes by checking for presence of a dynamic meta object and internal type names. This should also help skipping over QObject-derived classes written in Python which also have a dynamic meta object. Fixes: PYSIDE-2749 Task-number: PYSIDE-2404 Pick-to: 6.7 Change-Id: I029d104e59820fbf3dab52a3ac65b45d97b3c2e7 Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/pyside6/libpyside/pyside.cpp')
-rw-r--r--sources/pyside6/libpyside/pyside.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp
index 1a4050bf8..9e12e3cd7 100644
--- a/sources/pyside6/libpyside/pyside.cpp
+++ b/sources/pyside6/libpyside/pyside.cpp
@@ -43,6 +43,7 @@
#include <QtCore/QMutex>
#include <QtCore/QStack>
#include <QtCore/QThread>
+#include <QtCore/private/qobject_p.h>
#include <algorithm>
#include <cstring>
@@ -63,6 +64,20 @@ QT_END_NAMESPACE
Q_LOGGING_CATEGORY(lcPySide, "qt.pyside.libpyside", QtCriticalMsg)
+static QObjectData *qt_object_private(const QObject *o)
+{
+ class FriendlyQObject : public QObject {
+ public:
+ using QObject::d_ptr;
+ };
+ return static_cast<const FriendlyQObject *>(o)->d_ptr.data();
+}
+
+static bool hasDynamicMetaObject(const QObject *o)
+{
+ return qt_object_private(o)->metaObject != nullptr;
+}
+
namespace PySide
{
@@ -675,6 +690,32 @@ static void invalidatePtr(any_t *object)
static const char invalidatePropertyName[] = "_PySideInvalidatePtr";
+// PYSIDE-2749: Skip over internal QML classes and classes
+// with dynamic meta objects when looking for the best matching
+// type to avoid unnessarily triggering the lazy load mechanism
+// for classes that do not have a binding from things like eventFilter().
+static inline bool isInternalObject(const char *name)
+{
+ return std::strstr(name, "QMLTYPE") != nullptr || std::strstr(name, "QQmlPrivate") != nullptr;
+}
+
+static const QMetaObject *metaObjectCandidate(const QObject *o)
+{
+ auto *metaObject = o->metaObject();
+ // Skip QML helper types and Python objects
+ if (hasDynamicMetaObject(o)) {
+ if (auto *super = metaObject->superClass())
+ metaObject = super;
+ }
+ for (auto *candidate = metaObject; candidate != nullptr; candidate = candidate->superClass()) {
+ if (!isInternalObject(candidate->className())) {
+ metaObject = candidate;
+ break;
+ }
+ }
+ return metaObject;
+}
+
// PYSIDE-1214, when creating new wrappers for classes inheriting QObject but
// not exposed to Python, try to find the best-matching (most-derived) Qt
// class by walking up the meta objects.
@@ -682,7 +723,8 @@ static const char *typeName(const QObject *cppSelf)
{
const char *typeName = typeid(*cppSelf).name();
if (!Shiboken::Conversions::getConverter(typeName)) {
- for (auto metaObject = cppSelf->metaObject(); metaObject; metaObject = metaObject->superClass()) {
+ auto *metaObject = metaObjectCandidate(cppSelf);
+ for (; metaObject != nullptr; metaObject = metaObject->superClass()) {
const char *name = metaObject->className();
if (Shiboken::Conversions::getConverter(name)) {
typeName = name;