aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-05-05 11:23:03 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-05-11 12:56:21 +0200
commit8d03b13a59a5e3866c982eb14ca2dc57b687d218 (patch)
tree0a93eae7d9f55e77bcf4702c469e068f618e259b
parent745cce4391a8b6255605cb304d8bc14b11168423 (diff)
QML: Port QV4::CompiledData::Alias to new special integer bitfield
Pick-to: 5.15 6.2 6.3 Task-number: QTBUG-99545 Change-Id: I554f9f903a39a83eaf601fd4fd932f685bf343d0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
-rw-r--r--src/qml/common/qv4compileddata_p.h75
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp12
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp12
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h27
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp20
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp18
-rw-r--r--tools/qmltc/prototype/qml2cppdefaultpasses.cpp14
7 files changed, 127 insertions, 51 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index 1c3732fd00..ad43d30241 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -733,20 +733,31 @@ struct RequiredPropertyExtraData {
static_assert (sizeof(RequiredPropertyExtraData) == 4, "RequiredPropertyExtraData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Alias {
- enum Flags : unsigned int {
+private:
+ using NameIndexField = quint32_le_bitfield_member<0, 29>;
+ using FlagsField = quint32_le_bitfield_member<29, 3>;
+
+ // object id index (in QQmlContextData::idValues)
+ using TargetObjectIdField = quint32_le_bitfield_member<0, 31>;
+ using AliasToLocalAliasField = quint32_le_bitfield_member<31, 1>;
+
+public:
+
+ enum Flag : unsigned int {
IsReadOnly = 0x1,
Resolved = 0x2,
AliasPointsToPointerObject = 0x4
};
- union {
- quint32_le_bitfield<0, 29> nameIndex;
- quint32_le_bitfield<29, 3> flags;
- };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ quint32_le_bitfield_union<NameIndexField, FlagsField> nameIndexAndFlags;
+
union {
quint32_le idIndex; // string index
- quint32_le_bitfield<0, 31> targetObjectId; // object id index (in QQmlContextData::idValues)
- quint32_le_bitfield<31, 1> aliasToLocalAlias;
+ quint32_le_bitfield_union<TargetObjectIdField, AliasToLocalAliasField>
+ targetObjectIdAndAliasToLocalAlias;
};
+
union {
quint32_le propertyNameIndex; // string index
qint32_le encodedMetaPropertyIndex;
@@ -755,10 +766,56 @@ struct Alias {
Location location;
Location referenceLocation;
- bool isObjectAlias() const {
- Q_ASSERT(flags & Resolved);
+ bool hasFlag(Flag flag) const
+ {
+ return nameIndexAndFlags.get<FlagsField>() & flag;
+ }
+
+ void setFlag(Flag flag)
+ {
+ nameIndexAndFlags.set<FlagsField>(nameIndexAndFlags.get<FlagsField>() | flag);
+ }
+
+ void clearFlags()
+ {
+ nameIndexAndFlags.set<FlagsField>(0);
+ }
+
+ quint32 nameIndex() const
+ {
+ return nameIndexAndFlags.get<NameIndexField>();
+ }
+
+ void setNameIndex(quint32 nameIndex)
+ {
+ nameIndexAndFlags.set<NameIndexField>(nameIndex);
+ }
+
+ bool isObjectAlias() const
+ {
+ Q_ASSERT(hasFlag(Resolved));
return encodedMetaPropertyIndex == -1;
}
+
+ bool isAliasToLocalAlias() const
+ {
+ return targetObjectIdAndAliasToLocalAlias.get<AliasToLocalAliasField>();
+ }
+
+ void setIsAliasToLocalAlias(bool isAliasToLocalAlias)
+ {
+ targetObjectIdAndAliasToLocalAlias.set<AliasToLocalAliasField>(isAliasToLocalAlias);
+ }
+
+ quint32 targetObjectId() const
+ {
+ return targetObjectIdAndAliasToLocalAlias.get<TargetObjectIdField>();
+ }
+
+ void setTargetObjectId(quint32 targetObjectId)
+ {
+ targetObjectIdAndAliasToLocalAlias.set<TargetObjectIdField>(targetObjectId);
+ }
};
static_assert(sizeof(Alias) == 20, "Alias structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 1b0ecacdf3..c5453968ba 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -246,7 +246,7 @@ QString Object::appendProperty(Property *prop, const QString &propertyName, bool
return tr("Duplicate property name");
for (Alias *a = target->aliases->first; a; a = a->next)
- if (a->nameIndex == prop->nameIndex)
+ if (a->nameIndex() == prop->nameIndex)
return tr("Property duplicates alias name");
if (propertyName.constData()->isUpper())
@@ -270,13 +270,13 @@ QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefau
target = this;
const auto aliasWithSameName = std::find_if(target->aliases->begin(), target->aliases->end(), [&alias](const Alias &targetAlias){
- return targetAlias.nameIndex == alias->nameIndex;
+ return targetAlias.nameIndex() == alias->nameIndex();
});
if (aliasWithSameName != target->aliases->end())
return tr("Duplicate alias name");
const auto aliasSameAsProperty = std::find_if(target->properties->begin(), target->properties->end(), [&alias](const Property &targetProp){
- return targetProp.nameIndex == alias->nameIndex;
+ return targetProp.nameIndex == alias->nameIndex();
});
if (aliasSameAsProperty != target->properties->end())
@@ -1282,12 +1282,12 @@ void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocatio
bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node)
{
Alias *alias = New<Alias>();
- alias->flags = 0;
+ alias->clearFlags();
if (node->isReadonly())
- alias->flags |= QV4::CompiledData::Alias::IsReadOnly;
+ alias->setFlag(QV4::CompiledData::Alias::IsReadOnly);
const QString propName = node->name.toString();
- alias->nameIndex = registerString(propName);
+ alias->setNameIndex(registerString(propName));
QQmlJS::SourceLocation loc = node->firstSourceLocation();
alias->location.line = loc.startLine;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 49e05fdae0..f7656b9022 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -1659,12 +1659,12 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
for (int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
const auto originalAlias = alias;
- while (alias->aliasToLocalAlias)
+ while (alias->isAliasToLocalAlias())
alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ Q_ASSERT(alias->hasFlag(QV4::CompiledData::Alias::Resolved));
if (!context->isIdValueSet(0)) // TODO: Do we really want 0 here?
continue;
- QObject *target = context->idValue(alias->targetObjectId);
+ QObject *target = context->idValue(alias->targetObjectId());
if (!target)
continue;
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
@@ -1676,7 +1676,11 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
continue;
auto it = sharedState->requiredProperties.find(targetProperty);
if (it != sharedState->requiredProperties.end())
- it->aliasesToRequired.push_back(AliasToRequiredInfo {compilationUnit->stringAt(originalAlias->nameIndex), compilationUnit->finalUrl()});
+ it->aliasesToRequired.push_back(
+ AliasToRequiredInfo {
+ compilationUnit->stringAt(originalAlias->nameIndex()),
+ compilationUnit->finalUrl()
+ });
}
qSwap(_vmeMetaObject, vmeMetaObject);
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index 84c78a1973..ba060909fb 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -500,7 +500,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(
auto aend = obj->aliasesEnd();
for ( ; a != aend; ++a) {
bool notInRevision = false;
- const QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex), &notInRevision);
+ const QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex()), &notInRevision);
if (d && d->isFinal())
return qQmlCompileError(a->location, QQmlPropertyCacheCreatorBase::tr("Cannot override FINAL property"));
}
@@ -548,7 +548,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(
for ( ; a != aend; ++a) {
auto flags = QQmlPropertyData::defaultSignalFlags();
- QString changedSigName = stringAt(a->nameIndex) + QLatin1String("Changed");
+ QString changedSigName = stringAt(a->nameIndex()) + QLatin1String("Changed");
seenSignals.insert(changedSigName);
cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
@@ -836,12 +836,12 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
auto alias = object.aliasesBegin();
auto end = object.aliasesEnd();
for ( ; alias != end; ++alias) {
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ Q_ASSERT(alias->hasFlag(QV4::CompiledData::Alias::Resolved));
- const int targetObjectIndex = objectForId(component, alias->targetObjectId);
+ const int targetObjectIndex = objectForId(component, alias->targetObjectId());
Q_ASSERT(targetObjectIndex >= 0);
- if (alias->aliasToLocalAlias)
+ if (alias->isAliasToLocalAlias())
continue;
if (alias->encodedMetaPropertyIndex == -1)
@@ -912,12 +912,12 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
propertyFlags->setIsAlias(true);
- if (alias.aliasToLocalAlias) {
+ if (alias.isAliasToLocalAlias()) {
const QV4::CompiledData::Alias *lastAlias = &alias;
QVarLengthArray<const QV4::CompiledData::Alias *, 4> seenAliases({lastAlias});
do {
- const int targetObjectIndex = objectForId(component, lastAlias->targetObjectId);
+ const int targetObjectIndex = objectForId(component, lastAlias->targetObjectId());
Q_ASSERT(targetObjectIndex >= 0);
const CompiledObject *targetObject = objectContainer->objectAt(targetObjectIndex);
Q_ASSERT(targetObject);
@@ -934,17 +934,17 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
seenAliases.append(targetAlias);
lastAlias = targetAlias;
- } while (lastAlias->aliasToLocalAlias);
+ } while (lastAlias->isAliasToLocalAlias());
return propertyDataForAlias(component, *lastAlias, type, version, propertyFlags, enginePriv);
}
- const int targetObjectIndex = objectForId(component, alias.targetObjectId);
+ const int targetObjectIndex = objectForId(component, alias.targetObjectId());
Q_ASSERT(targetObjectIndex >= 0);
const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
if (alias.encodedMetaPropertyIndex == -1) {
- Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
+ Q_ASSERT(alias.hasFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject));
auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
if (!typeRef) {
// Can be caused by the alias target not being a valid id or property. E.g.:
@@ -1018,7 +1018,8 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
}
}
- propertyFlags->setIsWritable(!(alias.flags & QV4::CompiledData::Alias::IsReadOnly) && writable);
+ propertyFlags->setIsWritable(!(alias.hasFlag(QV4::CompiledData::Alias::IsReadOnly))
+ && writable);
propertyFlags->setIsResettable(resettable);
propertyFlags->setIsBindable(bindable);
return QQmlError();
@@ -1042,7 +1043,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
auto alias = object.aliasesBegin();
auto end = object.aliasesEnd();
for ( ; alias != end; ++alias, ++aliasIndex) {
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ Q_ASSERT(alias->hasFlag(QV4::CompiledData::Alias::Resolved));
QMetaType type;
QTypeRevision version = QTypeRevision::zero();
@@ -1052,7 +1053,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
if (error.isValid())
return error;
- const QString propertyName = objectContainer->stringAt(alias->nameIndex);
+ const QString propertyName = objectContainer->stringAt(alias->nameIndex());
if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias)
propertyCache->_defaultPropertyName = propertyName;
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index 3daff49d22..ea67b53bde 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -1065,7 +1065,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex)
if (!atLeastOneAliasResolved && !_objectsWithAliases.isEmpty()) {
const QmlIR::Object *obj = qmlObjects->at(_objectsWithAliases.first());
for (auto alias = obj->aliasesBegin(), end = obj->aliasesEnd(); alias != end; ++alias) {
- if (!(alias->flags & QV4::CompiledData::Alias::Resolved)) {
+ if (!alias->hasFlag(QV4::CompiledData::Alias::Resolved)) {
recordError(alias->location, tr("Circular alias reference detected"));
return false;
}
@@ -1087,7 +1087,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
bool seenUnresolvedAlias = false;
for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next) {
- if (alias->flags & QV4::CompiledData::Alias::Resolved)
+ if (alias->hasFlag(QV4::CompiledData::Alias::Resolved))
continue;
seenUnresolvedAlias = true;
@@ -1103,8 +1103,8 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
const QmlIR::Object *targetObject = qmlObjects->at(targetObjectIndex);
Q_ASSERT(targetObject->id >= 0);
- alias->targetObjectId = targetObject->id;
- alias->aliasToLocalAlias = false;
+ alias->setTargetObjectId(targetObject->id);
+ alias->setIsAliasToLocalAlias(false);
const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
@@ -1121,7 +1121,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
QQmlPropertyIndex propIdx;
if (property.isEmpty()) {
- alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
+ alias->setFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject);
} else {
QQmlPropertyCache::ConstPtr targetCache = propertyCaches.at(targetObjectIndex);
if (!targetCache) {
@@ -1140,7 +1140,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
bool aliasPointsToOtherAlias = false;
int localAliasIndex = 0;
for (auto targetAlias = targetObject->aliasesBegin(), end = targetObject->aliasesEnd(); targetAlias != end; ++targetAlias, ++localAliasIndex) {
- if (stringAt(targetAlias->nameIndex) == property) {
+ if (stringAt(targetAlias->nameIndex()) == property) {
aliasPointsToOtherAlias = true;
break;
}
@@ -1148,8 +1148,8 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
if (aliasPointsToOtherAlias) {
if (targetObjectIndex == objectIndex) {
alias->localAliasIndex = localAliasIndex;
- alias->aliasToLocalAlias = true;
- alias->flags |= QV4::CompiledData::Alias::Resolved;
+ alias->setIsAliasToLocalAlias(true);
+ alias->setFlag(QV4::CompiledData::Alias::Resolved);
++numResolvedAliases;
continue;
}
@@ -1211,12 +1211,12 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
}
} else {
if (targetProperty->isQObject())
- alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
+ alias->setFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject);
}
}
alias->encodedMetaPropertyIndex = propIdx.toEncoded();
- alias->flags |= QV4::CompiledData::Alias::Resolved;
+ alias->setFlag(QV4::CompiledData::Alias::Resolved);
numResolvedAliases++;
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 4ff4180201..0ee7e07579 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -235,7 +235,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
const QV4::CompiledData::Alias *aliasData = &metaObject->compiledObject->aliasTable()[aliasId];
if (!aliasData->isObjectAlias()) {
QQmlRefPointer<QQmlContextData> ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValue(aliasData->targetObjectId);
+ QObject *target = ctxt->idValue(aliasData->targetObjectId());
if (!target)
return;
@@ -975,16 +975,18 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (id < aliasCount) {
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[id];
- if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty)
- *reinterpret_cast<void **>(a[0]) = nullptr;
+ if (aliasData->hasFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject)
+ && c == QMetaObject::ReadProperty){
+ *reinterpret_cast<void **>(a[0]) = nullptr;
+ }
if (ctxt.isNull())
return -1;
- while (aliasData->aliasToLocalAlias)
+ while (aliasData->isAliasToLocalAlias())
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- QObject *target = ctxt->idValue(aliasData->targetObjectId);
+ QObject *target = ctxt->idValue(aliasData->targetObjectId());
if (!target)
return -1;
@@ -1331,9 +1333,9 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
const int aliasId = index - propOffset() - compiledObject->nProperties;
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
- while (aliasData->aliasToLocalAlias)
+ while (aliasData->isAliasToLocalAlias())
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- *target = ctxt->idValue(aliasData->targetObjectId);
+ *target = ctxt->idValue(aliasData->targetObjectId());
if (!*target)
return false;
@@ -1361,7 +1363,7 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
}
endpoint->metaObject = this;
- endpoint->connect(ctxt->idValueBindings(aliasData->targetObjectId));
+ endpoint->connect(ctxt->idValueBindings(aliasData->targetObjectId()));
endpoint->tryConnect();
}
diff --git a/tools/qmltc/prototype/qml2cppdefaultpasses.cpp b/tools/qmltc/prototype/qml2cppdefaultpasses.cpp
index ff7b8b12e8..48b97d3ded 100644
--- a/tools/qmltc/prototype/qml2cppdefaultpasses.cpp
+++ b/tools/qmltc/prototype/qml2cppdefaultpasses.cpp
@@ -147,12 +147,24 @@ static bool isReservedWord(QStringView word)
return std::binary_search(std::begin(cppKeywords), std::end(cppKeywords), word);
}
+template<typename IRElement>
+quint32 irNameIndex(const IRElement &irElement)
+{
+ return irElement.nameIndex;
+}
+
+template<>
+quint32 irNameIndex<QmlIR::Alias>(const QmlIR::Alias &alias)
+{
+ return alias.nameIndex();
+}
+
template<typename InputIterator>
static decltype(auto) findIrElement(const QmlIR::Document *doc, InputIterator first,
InputIterator last, QStringView name)
{
auto it = std::find_if(first, last, [&](const auto &candidate) {
- return name == doc->stringAt(candidate.nameIndex);
+ return name == doc->stringAt(irNameIndex(candidate));
});
Q_ASSERT(it != last); // must be satisfied by the caller
return *it;