From c13d4f62b4eaef8b80cce4ce488d70c3afd43077 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 5 May 2022 12:17:11 +0200 Subject: QML: Port QV4::CompiledData::Object to new special integer bitfield Task-number: QTBUG-99545 Change-Id: Ia57a16313e883a8d4dab15c971181440ed1d2214 Reviewed-by: Fabian Kosmale Reviewed-by: Sami Shalayel (cherry picked from commit 745cce4391a8b6255605cb304d8bc14b11168423) --- src/qml/common/qv4compileddata_p.h | 57 +++++++++++++++++++--- src/qml/compiler/qqmlirbuilder.cpp | 6 +-- src/qml/compiler/qqmlirbuilder_p.h | 4 ++ src/qml/inlinecomponentutils_p.h | 7 ++- src/qml/jsruntime/qv4executablecompilationunit.cpp | 13 ++--- src/qml/qml/qqmlirloader.cpp | 6 +-- src/qml/qml/qqmlobjectcreator.cpp | 16 +++--- src/qml/qml/qqmlpropertycachecreator_p.h | 12 ++--- src/qml/qml/qqmlpropertyvalidator.cpp | 3 +- src/qmltest/quicktest.cpp | 2 +- 10 files changed, 90 insertions(+), 36 deletions(-) diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index 333878ef25..fb4c13c81d 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -798,7 +798,12 @@ static_assert(sizeof(Alias) == 20, "Alias structure needs to have the expected s struct Object { - enum Flags : unsigned int { +private: + using FlagsField = quint32_le_bitfield_member<0, 15>; + using DefaultPropertyIsAliasField = quint32_le_bitfield_member<15, 1>; + using IdField = quint32_le_bitfield_member<16, 16, qint32>; +public: + enum Flag : unsigned int { NoFlag = 0x0, IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary HasDeferredBindings = 0x2, // any of the bindings are deferred @@ -806,17 +811,15 @@ struct Object IsInlineComponentRoot = 0x8, InPartOfInlineComponent = 0x10 }; + Q_DECLARE_FLAGS(Flags, Flag); // Depending on the use, this may be the type name to instantiate before instantiating this // object. For grouped properties the type name will be empty and for attached properties // it will be the name of the attached type. quint32_le inheritedTypeNameIndex; quint32_le idNameIndex; - union { - quint32_le_bitfield<0, 15> flags; - quint32_le_bitfield<15, 1> defaultPropertyIsAlias; - qint32_le_bitfield<16, 16> id; - }; + quint32_le_bitfield_union + flagsAndDefaultPropertyIsAliasAndId; qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object quint16_le nFunctions; quint16_le nProperties; @@ -845,6 +848,48 @@ struct Object // InlineComponent[] // RequiredPropertyExtraData[] + Flags flags() const + { + return Flags(flagsAndDefaultPropertyIsAliasAndId.get()); + } + + bool hasFlag(Flag flag) const + { + return flagsAndDefaultPropertyIsAliasAndId.get() & flag; + } + + void setFlag(Flag flag) + { + flagsAndDefaultPropertyIsAliasAndId.set( + flagsAndDefaultPropertyIsAliasAndId.get() | flag); + } + + void setFlags(Flags flags) + { + flagsAndDefaultPropertyIsAliasAndId.set(flags); + } + + bool hasAliasAsDefaultProperty() const + { + return flagsAndDefaultPropertyIsAliasAndId.get(); + } + + void setHasAliasAsDefaultProperty(bool defaultAlias) + { + flagsAndDefaultPropertyIsAliasAndId.set(defaultAlias); + } + + qint32 objectId() const + { + return flagsAndDefaultPropertyIsAliasAndId.get(); + } + + void setObjectId(qint32 id) + { + flagsAndDefaultPropertyIsAliasAndId.set(id); + } + + static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData) { return ( sizeof(Object) diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index b5210e6510..20c6b9d290 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1664,10 +1664,10 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen QV4::CompiledData::Object *objectToWrite = reinterpret_cast(objectPtr); objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex; objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias; - objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias; - objectToWrite->flags = o->flags; + objectToWrite->setHasAliasAsDefaultProperty(o->defaultPropertyIsAlias); + objectToWrite->setFlags(QV4::CompiledData::Object::Flags(o->flags)); objectToWrite->idNameIndex = o->idNameIndex; - objectToWrite->id = o->id; + objectToWrite->setObjectId(o->id); objectToWrite->location = o->location; objectToWrite->locationOfIdProperty = o->locationOfIdProperty; diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 213d43134a..0f1ae70bfa 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -393,6 +393,10 @@ public: int namedObjectsInComponentCount() const { return namedObjectsInComponent.size(); } const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); } + bool hasFlag(QV4::CompiledData::Object::Flag flag) const { return flags & flag; } + qint32 objectId() const { return id; } + bool hasAliasAsDefaultProperty() const { return defaultPropertyIsAlias; } + private: friend struct ::QQmlIRLoader; diff --git a/src/qml/inlinecomponentutils_p.h b/src/qml/inlinecomponentutils_p.h index 41333cbb1b..56794779a6 100644 --- a/src/qml/inlinecomponentutils_p.h +++ b/src/qml/inlinecomponentutils_p.h @@ -123,8 +123,11 @@ void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, Adja auto referencedInICObjectIndex = ic.objectIndex + 1; while (int(referencedInICObjectIndex) < objectContainer->objectCount()) { auto potentiallyReferencedInICObject = objectContainer->objectAt(referencedInICObjectIndex); - bool stillInIC = !(potentiallyReferencedInICObject-> flags & QV4::CompiledData::Object::IsInlineComponentRoot) - && (potentiallyReferencedInICObject-> flags & QV4::CompiledData::Object::InPartOfInlineComponent); + bool stillInIC + = !potentiallyReferencedInICObject->hasFlag( + QV4::CompiledData::Object::IsInlineComponentRoot) + && potentiallyReferencedInICObject->hasFlag( + QV4::CompiledData::Object::InPartOfInlineComponent); if (!stillInIC) break; createEdgeFromTypeRef(objectContainer->resolvedType(potentiallyReferencedInICObject->inheritedTypeNameIndex)); diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index 9a6f0de37d..ab5cd9363f 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -390,7 +390,7 @@ IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int com const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable(); for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) { const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr); - namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id); + namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->objectId()); } Q_ASSERT(!namedObjectCache.isEmpty()); return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache); @@ -446,9 +446,10 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi int lastICRoot = ic.objectIndex; for (int i = ic.objectIndex; iflags & QV4::CompiledData::Object::IsInlineComponentRoot) - || !(obj->flags & QV4::CompiledData::Object::InPartOfInlineComponent); + bool leftCurrentInlineComponent + = (i != lastICRoot + && obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot)) + || !obj->hasFlag(QV4::CompiledData::Object::InPartOfInlineComponent); if (leftCurrentInlineComponent) break; inlineComponentData[lastICRoot].totalBindingCount += obj->nBindings; @@ -478,9 +479,9 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi int objectCount = 0; for (quint32 i = 0, count = this->objectCount(); i < count; ++i) { const QV4::CompiledData::Object *obj = objectAt(i); - if (obj->flags & QV4::CompiledData::Object::InPartOfInlineComponent) { + if (obj->hasFlag(QV4::CompiledData::Object::InPartOfInlineComponent)) continue; - } + bindingCount += obj->nBindings; if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { const auto type = typeRef->type(); diff --git a/src/qml/qml/qqmlirloader.cpp b/src/qml/qml/qqmlirloader.cpp index 7b871a419a..2e3f6cabe9 100644 --- a/src/qml/qml/qqmlirloader.cpp +++ b/src/qml/qml/qqmlirloader.cpp @@ -107,9 +107,9 @@ QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *seriali serializedObject->location); object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias; - object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias; - object->flags = serializedObject->flags; - object->id = serializedObject->id; + object->defaultPropertyIsAlias = serializedObject->hasAliasAsDefaultProperty(); + object->flags = serializedObject->flags(); + object->id = serializedObject->objectId(); object->locationOfIdProperty = serializedObject->locationOfIdProperty; QVector functionIndices; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index cd94304b52..a4140e8a57 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -819,7 +819,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper for (int i = 0, end = compilationUnit->objectCount(); i != end; ++i) { const QV4::CompiledData::Object *external = compilationUnit->objectAt(i); if (external->idNameIndex == binding->propertyNameIndex) { - bindingTarget = groupObject = context->idValue(external->id); + bindingTarget = groupObject = context->idValue(external->objectId()); break; } } @@ -1170,8 +1170,8 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const { - if (object->id >= 0) - context->setIdValue(object->id, instance); + if (object->objectId() >= 0) + context->setIdValue(object->objectId(), instance); } QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject) @@ -1191,7 +1191,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QQmlParserStatus *parserStatus = nullptr; bool installPropertyCache = true; - if (obj->flags & QV4::CompiledData::Object::IsComponent) { + if (obj->hasFlag(QV4::CompiledData::Object::IsComponent)) { isComponent = true; instance = createComponent(engine, compilationUnit.data(), index, parent, context); typeName = QStringLiteral(""); @@ -1293,7 +1293,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo // an additional check const bool documentRoot = static_cast(index) == /*root object*/ 0 || ddata->rootObjectInCreation - || (obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot); + || obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot); context->installContext( ddata, documentRoot ? QQmlContextData::DocumentRoot : QQmlContextData::OrdinaryObject); @@ -1311,7 +1311,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo if (isContextObject) context->setContextObject(instance); - if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) { + if (customParser && obj->hasFlag(QV4::CompiledData::Object::HasCustomParserBindings)) { customParser->engine = QQmlEnginePrivate::get(engine); customParser->imports = compilationUnit->typeNameCache.data(); @@ -1542,7 +1542,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * qSwap(_vmeMetaObject, vmeMetaObject); _ddata->compilationUnit = compilationUnit; - if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) + if (_compiledObject->hasFlag(QV4::CompiledData::Object::HasDeferredBindings)) _ddata->deferData(_compiledObjectIndex, compilationUnit, context); const qsizetype oldRequiredPropertiesCount = sharedState->requiredProperties.size(); @@ -1592,7 +1592,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * Q_ASSERT(binding->isGroupProperty()); return { 0, _propertyCache->propertyOffset() + 1 }; // 4. } - Q_ASSERT(!(_compiledObject->flags & QV4::CompiledData::Object::IsComponent)); + Q_ASSERT(!_compiledObject->hasFlag(QV4::CompiledData::Object::IsComponent)); QQmlType type = typeRef->type(); if (type.isValid() && !type.isInlineComponentType()) { return { 0, _propertyCache->propertyCount() }; // 1. diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index c1f9175876..f6d85f9214 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -290,7 +290,7 @@ inline QQmlError QQmlPropertyCacheCreator::buildMetaObjectRecur const CompiledObject *obj = objectContainer->objectAt(objectIndex); bool needVMEMetaObject = isVMERequired == VMEMetaObjectIsRequired::Always || obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0 - || (((obj->flags & QV4::CompiledData::Object::IsComponent) + || ((obj->hasFlag(QV4::CompiledData::Object::IsComponent) || (objectIndex == 0 && isAddressable(objectContainer->url()))) && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType()); @@ -719,7 +719,7 @@ inline QQmlError QQmlPropertyCacheCreator::createMetaObject(int QString propertyName = stringAt(p->nameIndex); - if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias) + if (!obj->hasAliasAsDefaultProperty() && propertyIdx == obj->indexOfDefaultPropertyOrAlias) cache->_defaultPropertyName = propertyName; cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, propertyType, propertyTypeVersion, effectiveSignalIndex); @@ -805,7 +805,7 @@ inline void QQmlPropertyCacheAliasCreator::appendAliasPropertie // from a binding. for (int i = 1; i < objectContainer->objectCount(); ++i) { const CompiledObject &component = *objectContainer->objectAt(i); - if (!(component.flags & QV4::CompiledData::Object::IsComponent)) + if (!component.hasFlag(QV4::CompiledData::Object::IsComponent)) continue; const auto rootBinding = component.bindingsBegin(); @@ -875,7 +875,7 @@ inline void QQmlPropertyCacheAliasCreator::collectObjectsWithAl objectsWithAliases->append(objectIndex); // Stop at Component boundary - if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != /*root object*/0) + if (object.hasFlag(QV4::CompiledData::Object::IsComponent) && objectIndex != /*root object*/0) return; auto binding = object.bindingsBegin(); @@ -1048,7 +1048,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator::appendAliasesTo const QString propertyName = objectContainer->stringAt(alias->nameIndex); - if (object.defaultPropertyIsAlias && aliasIndex == object.indexOfDefaultPropertyOrAlias) + if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias) propertyCache->_defaultPropertyName = propertyName; propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++, @@ -1064,7 +1064,7 @@ inline int QQmlPropertyCacheAliasCreator::objectForId(const Com for (quint32 i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) { const int candidateIndex = component.namedObjectsInComponentTable()[i]; const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex); - if (candidate.id == id) + if (candidate.objectId() == id) return candidateIndex; } return -1; diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp index 023a945e94..1f6c0e0739 100644 --- a/src/qml/qml/qqmlpropertyvalidator.cpp +++ b/src/qml/qml/qqmlpropertyvalidator.cpp @@ -107,7 +107,8 @@ QVector QQmlPropertyValidator::validateObject( return errors; } - if (obj->flags & QV4::CompiledData::Object::IsComponent && !(obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot)) { + if (obj->hasFlag(QV4::CompiledData::Object::IsComponent) + && !obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot)) { Q_ASSERT(obj->nBindings == 1); const QV4::CompiledData::Binding *componentBinding = obj->bindingTable(); Q_ASSERT(componentBinding->type() == QV4::CompiledData::Binding::Type_Object); diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index b453b288bd..5cfff6ddaa 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -302,7 +302,7 @@ private: if (!object) // Start at root of compilation unit if not enumerating a specific child object = compilationUnit->objectAt(0); - if (object->flags & Object::IsInlineComponentRoot) + if (object->hasFlag(Object::IsInlineComponentRoot)) return result; if (const auto superTypeUnit = compilationUnit->resolvedTypes.value( -- cgit v1.2.3