diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-11-07 17:37:18 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-11-10 15:00:11 +0100 |
commit | c337db8d7ee77ea3aaafd6a065a34865319dbe5e (patch) | |
tree | dacde68958d0c5af43e9d7b72d0c791da3c574d2 /src | |
parent | c949d7ede355caf559f059fe124eb3dda02c8dc4 (diff) |
ConstructionState: reduce size
We can reduce the size of the class by using QBiPointer to internally
store what previously has been two pointers and a flag.
The only draw-back is that we now have to manually manage the memory.
Mark the type as uncopieable to reduce the amount of boilerplate we
need; we still need to support moves as we store ConstructionState in a
vector.
Change-Id: I99329bbfda3f7147d475c1574a20a54719d2f7bd
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 90 |
2 files changed, 75 insertions, 16 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index f27e551997..2c4e6b28d5 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1033,6 +1033,7 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(rv); for (int i = 0, propertyCount = propertyCache->propertyCount(); i < propertyCount; ++i) { if (const QQmlPropertyData *propertyData = propertyCache->property(i); propertyData->isRequired()) { + state.ensureRequiredPropertyStorage(); RequiredPropertyInfo info; info.propertyName = propertyData->name(rv); state.addPendingRequiredProperty(propertyData, info); diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 4852beb3a3..1ff81f7775 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -26,6 +26,7 @@ #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QList> +#include <QtCore/qtclasshelpermacros.h> #include <private/qobject_p.h> @@ -92,6 +93,19 @@ public: }; struct ConstructionState { + ConstructionState() = default; + inline ~ConstructionState(); + Q_DISABLE_COPY(ConstructionState) + inline ConstructionState(ConstructionState &&other) noexcept; + + void swap(ConstructionState &other) + { + m_creatorOrRequiredProperties.swap(other.m_creatorOrRequiredProperties); + } + + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QQmlComponentPrivate::ConstructionState); + + inline void ensureRequiredPropertyStorage(); inline RequiredProperties *requiredProperties(); inline void addPendingRequiredProperty(const QQmlPropertyData *propData, const RequiredPropertyInfo &info); inline bool hasUnsetRequiredProperties() const; @@ -113,9 +127,7 @@ public: inline void setCompletePending(bool isPending); private: - bool m_completePending = false; - RequiredProperties m_requiredProperties; // todo: union with another member - std::unique_ptr<QQmlObjectCreator> m_creator; + QBiPointer<QQmlObjectCreator, RequiredProperties> m_creatorOrRequiredProperties; }; ConstructionState state; @@ -151,16 +163,31 @@ public: } }; +QQmlComponentPrivate::ConstructionState::~ConstructionState() +{ + if (m_creatorOrRequiredProperties.isT1()) + delete m_creatorOrRequiredProperties.asT1(); + else + delete m_creatorOrRequiredProperties.asT2(); +} + +QQmlComponentPrivate::ConstructionState::ConstructionState(ConstructionState &&other) noexcept +{ + errors = std::move(other.errors); + m_creatorOrRequiredProperties = std::exchange(other.m_creatorOrRequiredProperties, {}); +} /*! \internal A list of pending required properties that need to be set in order for object construction to be successful. */ inline RequiredProperties *QQmlComponentPrivate::ConstructionState::requiredProperties() { - if (hasCreator()) - return m_creator->requiredProperties(); + if (m_creatorOrRequiredProperties.isNull()) + return nullptr; + else if (m_creatorOrRequiredProperties.isT1()) + return m_creatorOrRequiredProperties.asT1()->requiredProperties(); else - return &m_requiredProperties; + return m_creatorOrRequiredProperties.asT2(); } inline void QQmlComponentPrivate::ConstructionState::addPendingRequiredProperty(const QQmlPropertyData *propData, const RequiredPropertyInfo &info) @@ -170,7 +197,8 @@ inline void QQmlComponentPrivate::ConstructionState::addPendingRequiredProperty( } inline bool QQmlComponentPrivate::ConstructionState::hasUnsetRequiredProperties() const { - return !const_cast<ConstructionState *>(this)->requiredProperties()->isEmpty(); + auto properties = const_cast<ConstructionState *>(this)->requiredProperties(); + return properties && !properties->isEmpty(); } inline void QQmlComponentPrivate::ConstructionState::clearRequiredProperties() @@ -202,34 +230,64 @@ inline void QQmlComponentPrivate::ConstructionState::appendCreatorErrors() inline QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::creator() { - return m_creator.get(); + if (m_creatorOrRequiredProperties.isT1()) + return m_creatorOrRequiredProperties.asT1(); + return nullptr; } inline const QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::creator() const { - return m_creator.get(); + if (m_creatorOrRequiredProperties.isT1()) + return m_creatorOrRequiredProperties.asT1(); + return nullptr; } -inline bool QQmlComponentPrivate::ConstructionState::hasCreator() const { return m_creator != nullptr; } +inline bool QQmlComponentPrivate::ConstructionState::hasCreator() const +{ + return creator() != nullptr; +} -inline void QQmlComponentPrivate::ConstructionState::clear() { m_creator.reset(); } +inline void QQmlComponentPrivate::ConstructionState::clear() +{ + if (m_creatorOrRequiredProperties.isT1()) { + delete m_creatorOrRequiredProperties.asT1(); + m_creatorOrRequiredProperties = static_cast<QQmlObjectCreator *>(nullptr); + } +} inline QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::initCreator(QQmlRefPointer<QQmlContextData> parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QQmlRefPointer<QQmlContextData> &creationContext) { - m_creator.reset(new QQmlObjectCreator( + if (m_creatorOrRequiredProperties.isT1()) + delete m_creatorOrRequiredProperties.asT1(); + else + delete m_creatorOrRequiredProperties.asT2(); + m_creatorOrRequiredProperties = new QQmlObjectCreator( std::move(parentContext), compilationUnit, - creationContext)); - return m_creator.get(); + creationContext); + return m_creatorOrRequiredProperties.asT1(); } inline bool QQmlComponentPrivate::ConstructionState::isCompletePending() const { - return m_completePending; + return m_creatorOrRequiredProperties.flag(); } inline void QQmlComponentPrivate::ConstructionState::setCompletePending(bool isPending) { - m_completePending = isPending; + m_creatorOrRequiredProperties.setFlagValue(isPending); +} + +/*! + \internal + This is meant to be used in the context of QQmlComponent::loadFromModule, + when dealing with a C++ type. In that case, we do not have a creator, + and need a separate storage for required properties. + */ +inline void QQmlComponentPrivate::ConstructionState::ensureRequiredPropertyStorage() +{ + Q_ASSERT(m_creatorOrRequiredProperties.isT2() || m_creatorOrRequiredProperties.isNull()); + if (m_creatorOrRequiredProperties.isNull()) + m_creatorOrRequiredProperties = new RequiredProperties; } QT_END_NAMESPACE |