diff options
| author | Thiago Macieira <thiago.macieira@intel.com> | 2024-08-27 21:11:29 -0700 |
|---|---|---|
| committer | Thiago Macieira <thiago.macieira@intel.com> | 2024-10-03 18:54:33 -0700 |
| commit | 518fa1baf7bbc93b80567691d682ae64032fde76 (patch) | |
| tree | 0a9d7088a20e0a633187e792e77edb1049b886f3 /src/corelib/kernel/qmetaobject.cpp | |
| parent | 20b6ebea84997ecd70d37640f68232c60cc7231f (diff) | |
QMetaMethod: make some QByteArray-returning methods slightly faster
QByteArray::fromRawData() allocates no memory. Since we know that the
data range is valid, there's no precondition violation either. But we
can only use it for static-lifetime meta objects: those constructed by
QMetaObjectBuilder or QtDBus may get deallocated, causing the strings
obtained from them to crash on use if they do outlive (unlikely, but not
impossible). To differentiate, this commit introduces a new flag to the
QMetaObject header and makes use of it in those two places.
Come Qt 7, we should change these functions to return QByteArrayView,
making the retention of the data in a QByteArray the responsibility of
the user. Making the change right now with #if or QTx_ONLY() is ugly, so
this commit just leaves a comment.
Change-Id: I5aaddbc7ce3fc7a70e15fffd29e276c79d5ef6e4
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Diffstat (limited to 'src/corelib/kernel/qmetaobject.cpp')
| -rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 48197c9d5c7..9e02098ccad 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -136,12 +136,23 @@ static inline QByteArrayView stringDataView(const QMetaObject *mo, int index) return {string, qsizetype(length)}; } -static inline QByteArray stringData(const QMetaObject *mo, int index) +static inline QByteArray stringData(const QMetaObject *mo, QByteArrayView view) { - const auto view = stringDataView(mo, index); + if (QMetaObjectPrivate::get(mo)->flags & AllocatedMetaObject) { + // allocate memory, in case the meta object disappears + return view.toByteArray(); + } + + // don't allocate memory: we assume that the meta object remains loaded + // forever (modern C++ libraries can't be unloaded from memory anyway) return QByteArray::fromRawData(view.data(), view.size()); } +static inline QByteArray stringData(const QMetaObject *mo, int index) +{ + return stringData(mo, stringDataView(mo, index)); +} + static inline QByteArrayView typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) { if (typeInfo & IsUnresolvedType) @@ -178,7 +189,7 @@ public: { return static_cast<const QMetaMethodPrivate *>(q); } inline QByteArray signature() const; - inline QByteArray name() const; + inline QByteArrayView name() const noexcept; inline int typesDataIndex() const; inline const char *rawReturnTypeName() const; inline int returnType() const; @@ -189,10 +200,10 @@ public: inline void getParameterTypes(int *types) const; inline const QtPrivate::QMetaTypeInterface *returnMetaTypeInterface() const; inline const QtPrivate::QMetaTypeInterface *const *parameterMetaTypeInterfaces() const; - inline QByteArray parameterTypeName(int index) const; + inline QByteArrayView parameterTypeName(int index) const noexcept; inline QList<QByteArray> parameterTypes() const; inline QList<QByteArray> parameterNames() const; - inline QByteArray tag() const; + inline const char *tag() const; inline int ownMethodIndex() const; inline int ownConstructorMethodIndex() const; @@ -1908,10 +1919,10 @@ QByteArray QMetaMethodPrivate::signature() const return result; } -QByteArray QMetaMethodPrivate::name() const +QByteArrayView QMetaMethodPrivate::name() const noexcept { Q_ASSERT(priv(mobj->d.data)->revision >= 7); - return stringData(mobj, data.name()); + return stringDataView(mobj, data.name()); } int QMetaMethodPrivate::typesDataIndex() const @@ -2022,10 +2033,10 @@ void QMetaMethodPrivate::getParameterTypes(int *types) const } } -QByteArray QMetaMethodPrivate::parameterTypeName(int index) const +QByteArrayView QMetaMethodPrivate::parameterTypeName(int index) const noexcept { int paramsIndex = parametersDataIndex(); - return typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + index]).toByteArray(); + return typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + index]); } QList<QByteArray> QMetaMethodPrivate::parameterTypes() const @@ -2054,10 +2065,10 @@ QList<QByteArray> QMetaMethodPrivate::parameterNames() const return list; } -QByteArray QMetaMethodPrivate::tag() const +const char *QMetaMethodPrivate::tag() const { Q_ASSERT(priv(mobj->d.data)->revision >= 7); - return stringData(mobj, data.tag()); + return rawStringData(mobj, data.tag()); } int QMetaMethodPrivate::ownMethodIndex() const @@ -2099,7 +2110,8 @@ QByteArray QMetaMethod::name() const { if (!mobj) return QByteArray(); - return QMetaMethodPrivate::get(this)->name(); + // ### Qt 7: change the return type and make noexcept + return stringData(mobj, QMetaMethodPrivate::get(this)->name()); } /*! @@ -2228,7 +2240,8 @@ QByteArray QMetaMethod::parameterTypeName(int index) const { if (!mobj || index < 0 || index >= parameterCount()) return {}; - return QMetaMethodPrivate::get(this)->parameterTypeName(index); + // ### Qt 7: change the return type and make noexcept + return stringData(mobj, QMetaMethodPrivate::get(this)->parameterTypeName(index)); } /*! @@ -2284,7 +2297,7 @@ const char *QMetaMethod::tag() const { if (!mobj) return nullptr; - return QMetaMethodPrivate::get(this)->tag().constData(); + return QMetaMethodPrivate::get(this)->tag(); } |
