aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-11-07 17:37:18 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2022-11-10 15:00:11 +0100
commitc337db8d7ee77ea3aaafd6a065a34865319dbe5e (patch)
treedacde68958d0c5af43e9d7b72d0c791da3c574d2 /src
parentc949d7ede355caf559f059fe124eb3dda02c8dc4 (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.cpp1
-rw-r--r--src/qml/qml/qqmlcomponent_p.h90
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