diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-10-06 13:30:19 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-10-12 19:14:47 +0200 |
commit | 63865ebd75ede8122011a19e58dc56c19978c91a (patch) | |
tree | 90f250b1c692475ea4d17407d39c82b3c80a97e5 /src/qml/qml | |
parent | 852c8d1d8a953c626735f044838454a4d249c225 (diff) |
Avoid QAbstractDynamicMetaObject where possible
We don't want to copy metaobjects, but QAbstractDynamicMetaObject forces
us. Rather, use plain QDynamicMetaObjectData, and store a pointer to the
actual metaobject.
This requires us to drop the "isDirect()" optimization for property
access, as we realize that there can be dynamic meta objects which are
not QAbstractDynamicMetaObject. However, this optimization was
questionable anyway. What it did was cache the fact that an object might
have a dynamic metaobject in a flag. Checking this on the object itself
should not be much more expensive, though. On the other hand, an object
might receive a dynamic metaobject individually without us adjusting
flags for its type. In that case we would call the wrong method.
Furthermore, most property access can be done using the static metacall
function anyway.
Change-Id: I5897351253496309721bd38adf3e35a1f069b080
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 24 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 50 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertydata_p.h | 37 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 41 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject_p.h | 4 |
13 files changed, 112 insertions, 93 deletions
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 6383643ebb..bd49fc3b51 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1530,7 +1530,6 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject QMetaObjectBuilder builder; clone(builder, extMetaObject, superdataBaseMetaObject, baseMetaObject); - builder.setFlags(MetaObjectFlag::DynamicMetaObject); QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = baseMetaObject; if (!metaObjects.isEmpty()) diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index ec2d57013f..24aff03fca 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -99,11 +99,6 @@ QByteArray QQmlOpenMetaObjectType::propertyName(int idx) const return d->mob.property(idx).name(); } -QMetaObject *QQmlOpenMetaObjectType::metaObject() const -{ - return d->mem; -} - void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names) { for (int i = 0; i < names.count(); ++i) { @@ -238,7 +233,7 @@ public: } QQmlOpenMetaObject *q; - QAbstractDynamicMetaObject *parent = nullptr; + QDynamicMetaObjectData *parent = nullptr; QVector<Property> data; QObject *object; QQmlRefPointer<QQmlOpenMetaObjectType> type; @@ -254,7 +249,7 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base) d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); - d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject); + d->parent = op->metaObject; *static_cast<QMetaObject *>(this) = *d->type->d->mem; op->metaObject = this; } @@ -266,7 +261,7 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *typ d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); - d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject); + d->parent = op->metaObject; *static_cast<QMetaObject *>(this) = *d->type->d->mem; op->metaObject = this; } @@ -292,6 +287,11 @@ void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName activate(d->object, *iter + d->type->d->signalOffset, nullptr); } +void QQmlOpenMetaObject::unparent() +{ + d->parent = nullptr; +} + int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a) { Q_ASSERT(d->object == o); @@ -319,7 +319,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void * } } -QAbstractDynamicMetaObject *QQmlOpenMetaObject::parent() const +QDynamicMetaObjectData *QQmlOpenMetaObject::parent() const { return d->parent; } diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h index 47bba085b5..e455725bdf 100644 --- a/src/qml/qml/qqmlopenmetaobject_p.h +++ b/src/qml/qml/qqmlopenmetaobject_p.h @@ -78,7 +78,6 @@ public: int propertyCount() const; QByteArray propertyName(int) const; - QMetaObject *metaObject() const; protected: virtual void propertyCreated(int, QMetaPropertyBuilder &); @@ -121,6 +120,7 @@ public: QQmlOpenMetaObjectType *type() const; void emitPropertyNotification(const QByteArray &propertyName); + void unparent(); protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; @@ -132,7 +132,7 @@ protected: virtual void propertyWritten(int); virtual void propertyCreated(int, QMetaPropertyBuilder &); - QAbstractDynamicMetaObject *parent() const; + QDynamicMetaObjectData *parent() const; bool checkedSetValue(int index, const QVariant &value, bool force); diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 315f9f07fa..5ed63fb57c 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -342,7 +342,7 @@ const QMetaObject *QQmlPropertyCache::createMetaObject() QMetaObjectBuilder builder; toMetaObjectBuilder(builder); builder.setSuperClass(_parent->createMetaObject()); - _metaObject = RefCountedMetaObject(builder.toMetaObject(), RefCountedMetaObject::SharedMetaObject); + _metaObject = RefCountedMetaObject::createShared(builder.toMetaObject()); } return _metaObject; @@ -403,10 +403,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) { - _metaObject = RefCountedMetaObject(metaObject, RefCountedMetaObject::StaticMetaObject); - - bool dynamicMetaObject = isDynamicMetaObject(metaObject); - + _metaObject = RefCountedMetaObject::createStatic(metaObject); allowedRevisionCache.append(QTypeRevision::zero()); int methodCount = metaObject->methodCount(); @@ -557,8 +554,6 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, data->load(p); data->setTypeVersion(typeVersion); - data->m_flags.setIsDirect(!dynamicMetaObject); - Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX); data->setMetaObjectOffset(allowedRevisionCache.count() - 1); @@ -586,9 +581,8 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, isGadget = false; } - if (isGadget) // always dispatch over a 'normal' meta-call so the QQmlValueType can intercept - data->m_flags.setIsDirect(false); - else + // otherwise always dispatch over a 'normal' meta-call so the QQmlValueType can intercept + if (!isGadget) data->trySetStaticMetaCallFunction(metaObject->d.static_metacall, ii - propOffset); } } @@ -969,10 +963,7 @@ QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QLatin1String return qQmlPropertyCacheProperty<const QLatin1String &>(engine, obj, name, context, local); } -// these two functions are copied from qmetaobject.cpp -static inline const QMetaObjectPrivate *priv(const uint* data) -{ return reinterpret_cast<const QMetaObjectPrivate*>(data); } - +// this function is copied from qmetaobject.cpp static inline const QByteArray stringData(const QMetaObject *mo, int index) { uint offset = mo->d.stringdata[2*index]; @@ -981,11 +972,6 @@ static inline const QByteArray stringData(const QMetaObject *mo, int index) return QByteArray::fromRawData(string, length); } -bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo) -{ - return priv(mo->d.data)->flags & DynamicMetaObject; -} - const char *QQmlPropertyCache::className() const { if (_metaObject) diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 93e776527e..1db3f0f464 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -84,8 +84,14 @@ public: }; struct Data { - ~Data() { if (mode == SharedMetaObject) ::free(const_cast<QMetaObject *>(mo)); } - const QMetaObject *mo = nullptr; + ~Data() { + if (mode == SharedMetaObject) + ::free(sharedMetaObject); + } + union { + QMetaObject *sharedMetaObject = nullptr; + const QMetaObject *staticMetaObject; + }; int ref = 1; OwnershipMode mode; } *d; @@ -94,11 +100,24 @@ public: : d(nullptr) {} - RefCountedMetaObject(const QMetaObject *mo, OwnershipMode mode) - : d(new Data) { - d->mo = mo; - d->mode = mode; + static RefCountedMetaObject createShared(QMetaObject *mo) + { + RefCountedMetaObject result; + result.d = new Data(); + result.d->sharedMetaObject = mo; + result.d->mode = SharedMetaObject; + return result; + } + + static RefCountedMetaObject createStatic(const QMetaObject *mo) + { + RefCountedMetaObject result; + result.d = new Data(); + result.d->staticMetaObject = mo; + result.d->mode = StaticMetaObject; + return result; } + ~RefCountedMetaObject() { if (d && !--d->ref) delete d; @@ -120,8 +139,21 @@ public: ++d->ref; return *this; } - operator const QMetaObject *() const { return d ? d->mo : nullptr; } - const QMetaObject * operator ->() const { return d ? d->mo : nullptr; } + + const QMetaObject *constMetaObject() const + { + if (!d) + return nullptr; + return isShared() ? d->sharedMetaObject : d->staticMetaObject; + } + + QMetaObject *sharedMetaObject() const + { + return isShared() ? d->sharedMetaObject : nullptr; + } + + operator const QMetaObject *() const { return constMetaObject(); } + const QMetaObject * operator ->() const { return constMetaObject(); } bool isShared() const { return d && d->mode == SharedMetaObject; } }; @@ -206,8 +238,6 @@ public: inline int signalOffset() const; inline int qmlEnumCount() const; - static bool isDynamicMetaObject(const QMetaObject *); - void toMetaObjectBuilder(QMetaObjectBuilder &); inline bool callJSFactoryMethod(QObject *object, void **args) const; diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h index edf777ff18..24e2204b71 100644 --- a/src/qml/qml/qqmlpropertydata_p.h +++ b/src/qml/qml/qqmlpropertydata_p.h @@ -104,7 +104,7 @@ public: // Lastly, isDirect and isOverridden apply to both functions and non-functions private: unsigned isConst : 1; // Property: has CONST flag/Method: is const - unsigned isDirectOrVMEFunction : 1; // Exists on a C++ QMetaOBject OR Function was added by QML + unsigned isVMEFunction : 1; // Function was added by QML unsigned isWritableORhasArguments : 1; // Has WRITE function OR Function takes arguments unsigned isResettableORisSignal : 1; // Has RESET function OR Function is a signal unsigned isAliasORisVMESignal : 1; // Is a QML alias to another property OR Signal was added by QML @@ -159,11 +159,6 @@ public: isConstructorORisBindable = b; } - void setIsDirect(bool b) { - Q_ASSERT(type != FunctionType); - isDirectOrVMEFunction = b; - } - void setIsRequired(bool b) { Q_ASSERT(type != FunctionType); isRequiredORisCloned = b; @@ -171,7 +166,7 @@ public: void setIsVMEFunction(bool b) { Q_ASSERT(type == FunctionType); - isDirectOrVMEFunction = b; + isVMEFunction = b; } void setHasArguments(bool b) { Q_ASSERT(type == FunctionType); @@ -233,7 +228,6 @@ public: bool isAlias() const { return !isFunction() && m_flags.isAliasORisVMESignal; } bool isFinal() const { return !isFunction() && m_flags.isFinalORisV4Function; } bool isOverridden() const { return m_flags.isOverridden; } - bool isDirect() const { return !isFunction() && m_flags.isDirectOrVMEFunction; } bool isRequired() const { return !isFunction() && m_flags.isRequiredORisCloned; } bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; } bool isFunction() const { return m_flags.type == Flags::FunctionType; } @@ -244,7 +238,7 @@ public: bool isQJSValue() const { return m_flags.type == Flags::QJSValueType; } bool isVarProperty() const { return m_flags.type == Flags::VarPropertyType; } bool isQVariant() const { return m_flags.type == Flags::QVariantType; } - bool isVMEFunction() const { return isFunction() && m_flags.isDirectOrVMEFunction; } + bool isVMEFunction() const { return isFunction() && m_flags.isVMEFunction; } bool hasArguments() const { return isFunction() && m_flags.isWritableORhasArguments; } bool isSignal() const { return isFunction() && m_flags.isResettableORisSignal; } bool isVMESignal() const { return isFunction() && m_flags.isAliasORisVMESignal; } @@ -353,14 +347,23 @@ public: readPropertyWithArgs(target, args); } - inline void readPropertyWithArgs(QObject *target, void *args[]) const + // This is the same as QMetaObject::metacall(), but inlined here to avoid a function call. + // And we ignore the return value. + template<QMetaObject::Call call> + void doMetacall(QObject *object, int idx, void **argv) const + { + if (QDynamicMetaObjectData *dynamicMetaObject = QObjectPrivate::get(object)->metaObject) + dynamicMetaObject->metaCall(object, call, idx, argv); + else + object->qt_metacall(call, idx, argv); + } + + void readPropertyWithArgs(QObject *target, void *args[]) const { if (hasStaticMetaCallFunction()) staticMetaCallFunction()(target, QMetaObject::ReadProperty, relativePropertyIndex(), args); - else if (isDirect()) - target->qt_metacall(QMetaObject::ReadProperty, coreIndex(), args); else - QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args); + doMetacall<QMetaObject::ReadProperty>(target, coreIndex(), args); } bool writeProperty(QObject *target, void *value, WriteFlags flags) const @@ -369,10 +372,8 @@ public: void *argv[] = { value, nullptr, &status, &flags }; if (flags.testFlag(BypassInterceptor) && hasStaticMetaCallFunction()) staticMetaCallFunction()(target, QMetaObject::WriteProperty, relativePropertyIndex(), argv); - else if (flags.testFlag(BypassInterceptor) && isDirect()) - target->qt_metacall(QMetaObject::WriteProperty, coreIndex(), argv); else - QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv); + doMetacall<QMetaObject::WriteProperty>(target, coreIndex(), argv); return true; } @@ -437,7 +438,7 @@ bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const QQmlPropertyData::Flags::Flags() : otherBits(0) , isConst(false) - , isDirectOrVMEFunction(false) + , isVMEFunction(false) , isWritableORhasArguments(false) , isResettableORisSignal(false) , isAliasORisVMESignal(false) @@ -454,7 +455,7 @@ QQmlPropertyData::Flags::Flags() bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) const { return isConst == other.isConst && - isDirectOrVMEFunction == other.isDirectOrVMEFunction && + isVMEFunction == other.isVMEFunction && isWritableORhasArguments == other.isWritableORhasArguments && isResettableORisSignal == other.isResettableORisSignal && isAliasORisVMESignal == other.isAliasORisVMESignal && diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp index 21d3c7ed05..33b216ee78 100644 --- a/src/qml/qml/qqmlproxymetaobject.cpp +++ b/src/qml/qml/qqmlproxymetaobject.cpp @@ -45,11 +45,11 @@ QT_BEGIN_NAMESPACE QQmlProxyMetaObject::QQmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList) : metaObjects(mList), proxies(nullptr), parent(nullptr), object(obj) { - *static_cast<QMetaObject *>(this) = *metaObjects->constFirst().metaObject; + metaObject = metaObjects->constFirst().metaObject; QObjectPrivate *op = QObjectPrivate::get(obj); if (op->metaObject) - parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject); + parent = op->metaObject; op->metaObject = this; } @@ -145,4 +145,9 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void return object->qt_metacall(c, id, a); } +QMetaObject *QQmlProxyMetaObject::toDynamicMetaObject(QObject *) +{ + return metaObject; +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h index dfa5d44059..3eb25caa7b 100644 --- a/src/qml/qml/qqmlproxymetaobject_p.h +++ b/src/qml/qml/qqmlproxymetaobject_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE -class QQmlProxyMetaObject : public QAbstractDynamicMetaObject +class QQmlProxyMetaObject : public QDynamicMetaObjectData { public: struct ProxyData { @@ -78,6 +78,7 @@ public: protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; + QMetaObject *toDynamicMetaObject(QObject *) override; private: QObject *getProxy(int index); @@ -85,7 +86,8 @@ private: QList<ProxyData> *metaObjects; QObject **proxies; - QAbstractDynamicMetaObject *parent; + QDynamicMetaObjectData *parent; + QMetaObject *metaObject; QObject *object; }; diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index f9f40e7ec6..4b1e84f236 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -228,7 +228,6 @@ void QQmlTypePrivate::init() const // XXX - very inefficient QMetaObjectBuilder builder; QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject); - builder.setFlags(MetaObjectFlag::DynamicMetaObject); QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = mo; QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 }; diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 7446322019..69baa03f74 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -52,7 +52,6 @@ QQmlValueType::QQmlValueType(QMetaType type, const QMetaObject *gadgetMetaObject { QMetaObjectBuilder builder(gadgetMetaObject); dynamicMetaObject = builder.toMetaObject(); - *static_cast<QMetaObject*>(this) = *dynamicMetaObject; } QQmlValueType::~QQmlValueType() @@ -113,7 +112,7 @@ void QQmlGadgetPtrWrapper::setValue(const QVariant &value) int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv) { Q_ASSERT(m_gadgetPtr); - const QMetaObject *metaObject = valueType(); + const QMetaObject *metaObject = valueType()->metaObject(); QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &id); metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv); return id; @@ -127,7 +126,7 @@ const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const QMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) { - return this; + return dynamicMetaObject; } void QQmlValueType::objectDestroyed(QObject *) diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index b1e985ba7a..c8e2945413 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlValueType : public QAbstractDynamicMetaObject +class Q_QML_PRIVATE_EXPORT QQmlValueType : public QDynamicMetaObjectData { public: QQmlValueType() : metaType(QMetaType::UnknownType) {} @@ -81,6 +81,7 @@ public: void destruct(void *gadgetPtr) const { metaType.destruct(gadgetPtr); } int metaTypeId() const { return metaType.id(); } + const QMetaObject *metaObject() const { return dynamicMetaObject; } // ---- dynamic meta object data interface QMetaObject *toDynamicMetaObject(QObject *) override; @@ -109,7 +110,7 @@ public: int metaTypeId() const { return valueType()->metaTypeId(); } int metaCall(QMetaObject::Call type, int id, void **argv); - QMetaProperty property(int index) { return valueType()->property(index); } + QMetaProperty property(int index) { return valueType()->metaObject()->property(index); } private: const QQmlValueType *valueType() const; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 99663d9daa..ea4c9f6c6f 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -79,12 +79,13 @@ public: m_id = encodedIndex & ((quintptr(1) << (usableBits / 2)) - 1); // walk up to the correct meta object if necessary - auto mo = prop->object->metaObject(); + auto mo = static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(prop->object)->metaObject); while (inheritanceDepth--) - mo = mo->superClass(); - m_metaObject = static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(mo)); + mo = mo->parentVMEMetaObject(); + m_metaObject = mo; Q_ASSERT(m_metaObject); - Q_ASSERT( ::strstr(m_metaObject->property(m_metaObject->propOffset() + m_id).typeName(), "QQmlListProperty") ); + Q_ASSERT(::strstr(m_metaObject->toDynamicMetaObject(prop->object)->property( + m_metaObject->propOffset() + m_id).typeName(), "QQmlListProperty") ); Q_ASSERT(m_metaObject->object == prop->object); // readPropertyAsList() with checks transformed into Q_ASSERT @@ -272,7 +273,7 @@ QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, const QQmlRef : object(obj), cache(cache), interceptors(nullptr), - hasAssignedMetaObjectData(false) + metaObject(nullptr) { QObjectPrivate *op = QObjectPrivate::get(obj); @@ -400,18 +401,13 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) QMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObject *o) { - if (!hasAssignedMetaObjectData) { - *static_cast<QMetaObject *>(this) = *cache->createMetaObject(); - - if (parent.isT1()) - this->d.superdata = parent.asT1()->toDynamicMetaObject(o); - else - this->d.superdata = parent.asT2(); - - hasAssignedMetaObjectData = true; - } + Q_UNUSED(o); + if (!metaObject) + metaObject = cache->createMetaObject(); - return this; + // ### Qt7: The const_cast is only due to toDynamicMetaObject having the wrong return type. + // It should be const QMetaObject *. Fix this. + return const_cast<QMetaObject *>(metaObject); } QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine, @@ -777,10 +773,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * // To do this, we encode the hierarchy depth together with the id of the // property in a single quintptr, with the first half storing the depth // and the second half storing the property id - auto mo = object->metaObject(); + auto mo = static_cast<QQmlVMEMetaObject *>( + QObjectPrivate::get(object)->metaObject); quintptr inheritanceDepth = 0u; while (mo && mo != this) { - mo = mo->superClass(); + mo = mo->parentVMEMetaObject(); ++inheritanceDepth; } constexpr quintptr usableBits = sizeof(quintptr) * CHAR_BIT; @@ -996,10 +993,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * // are not rewritten correctly but this bug is deemed out-of-scope to fix for // performance reasons; see QTBUG-24064) and thus compilation will have failed. QQmlError e; - e.setDescription(QLatin1String("Exception occurred during compilation of " - "function: ") - + QString::fromUtf8(QMetaObject::method(_id) - .methodSignature())); + e.setDescription( + QStringLiteral( + "Exception occurred during compilation of function: ") + + QString::fromUtf8(metaObject->method(_id).methodSignature())); ep->warning(e); return -1; // The dynamic method with that id is not available. } diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 41b9a42b51..885efa01c5 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -89,7 +89,7 @@ public: }; -class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QAbstractDynamicMetaObject +class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QDynamicMetaObjectData { public: QQmlInterceptorMetaObject(QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache); @@ -125,7 +125,7 @@ public: QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent; QQmlPropertyValueInterceptor *interceptors; - bool hasAssignedMetaObjectData; + const QMetaObject *metaObject; }; inline QQmlInterceptorMetaObject *QQmlInterceptorMetaObject::get(QObject *obj) |