aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <[email protected]>2016-06-20 10:26:40 +0200
committerSimon Hausmann <[email protected]>2016-07-15 20:31:51 +0000
commit8f19045ef5d308231716ddcb62a80cc43ebb2dd7 (patch)
treead69181c5d22d4366799632bd77ea57500d63a47 /src/qml/compiler
parentbf5f97e6c6900535a7131c6a26415459bfaca774 (diff)
Split out creation of alias properties in the property caches
Similar to the regular property cache creation code, this also has to become a template function so that it can be run on the compilation units loaded from disk in the future. What is shared between the code path of a fresh compilation vs. re-use of a unit from disk is the code to propagate the CompiledData::Alias entries into entries in the property cache. The code for iterating through the component spaces and resolving the alias references is not shared. Change-Id: I04c2a5575310400156b457ae7b709cffecb7455e Reviewed-by: Lars Knoll <[email protected]>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h2
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h234
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp128
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h4
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
5 files changed, 250 insertions, 120 deletions
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 4e0d4e563b..821a6bba6d 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -400,6 +400,8 @@ public:
FixedPoolArray<int> runtimeFunctionIndices;
FixedPoolArray<quint32> namedObjectsInComponent;
+ int namedObjectsInComponentCount() const { return namedObjectsInComponent.count; }
+ const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); }
private:
friend struct IRLoader;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index ff8bc49e6f..09a093d911 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -507,6 +507,240 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
return noError;
}
+template <typename ObjectContainer>
+class QQmlPropertyCacheAliasCreator
+{
+public:
+ typedef typename ObjectContainer::CompiledObject CompiledObject;
+
+ QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer);
+
+ void appendAliasPropertiesToMetaObjects();
+
+ void appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex);
+
+private:
+ void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex);
+ void propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, quint32 *propertyFlags);
+
+ void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const;
+
+ int objectForId(const CompiledObject &component, int id) const;
+
+ QQmlPropertyCacheVector *propertyCaches;
+ const ObjectContainer *objectContainer;
+};
+
+template <typename ObjectContainer>
+inline QQmlPropertyCacheAliasCreator<ObjectContainer>::QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
+ : propertyCaches(propertyCaches)
+ , objectContainer(objectContainer)
+{
+
+}
+
+template <typename ObjectContainer>
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesToMetaObjects()
+{
+ for (int i = 0; i < objectContainer->objectCount(); ++i) {
+ const CompiledObject &component = *objectContainer->objectAt(i);
+ if (!(component.flags & QV4::CompiledData::Object::IsComponent))
+ continue;
+
+ const auto rootBinding = component.bindingsBegin();
+ appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex);
+ }
+
+ const int rootObjectIndex = objectContainer->rootObjectIndex();
+ appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex);
+}
+
+template <typename ObjectContainer>
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex)
+{
+ QVector<int> objectsWithAliases;
+ collectObjectsWithAliasesRecursively(firstObjectIndex, &objectsWithAliases);
+ if (objectsWithAliases.isEmpty())
+ return;
+
+ const auto allAliasTargetsExist = [this, &component](const CompiledObject &object) {
+ for (auto alias = object.aliasesBegin(), end = object.aliasesEnd(); alias != end; ++alias) {
+ Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+
+ const int targetObjectIndex = objectForId(component, alias->targetObjectId);
+ Q_ASSERT(targetObjectIndex >= 0);
+
+ if (alias->encodedMetaPropertyIndex == -1)
+ continue;
+
+ const QQmlPropertyCache *targetCache = propertyCaches->at(targetObjectIndex);
+ Q_ASSERT(targetCache);
+
+ int coreIndex;
+ QQmlPropertyData::decodeValueTypePropertyIndex(alias->encodedMetaPropertyIndex, &coreIndex);
+ QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
+ if (!targetProperty)
+ return false;
+ }
+ return true;
+ };
+
+ do {
+ QVector<int> pendingObjects;
+
+ for (int objectIndex: qAsConst(objectsWithAliases)) {
+ const CompiledObject &object = *objectContainer->objectAt(objectIndex);
+
+ if (allAliasTargetsExist(object)) {
+ appendAliasesToPropertyCache(component, objectIndex);
+ } else {
+ pendingObjects.append(objectIndex);
+ }
+
+ }
+ qSwap(objectsWithAliases, pendingObjects);
+ } while (!objectsWithAliases.isEmpty());
+}
+
+template <typename ObjectContainer>
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const
+{
+ const CompiledObject &object = *objectContainer->objectAt(objectIndex);
+ if (object.aliasCount() > 0)
+ objectsWithAliases->append(objectIndex);
+
+ // Stop at Component boundary
+ if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != objectContainer->rootObjectIndex())
+ return;
+
+ for (auto binding = object.bindingsBegin(), end = object.bindingsEnd(); binding != end; ++binding) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Object
+ && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
+ && binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
+ continue;
+
+ collectObjectsWithAliasesRecursively(binding->value.objectIndex, objectsWithAliases);
+ }
+}
+
+template <typename ObjectContainer>
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, quint32 *propertyFlags)
+{
+ const int targetObjectIndex = objectForId(component, alias.targetObjectId);
+ Q_ASSERT(targetObjectIndex >= 0);
+
+ const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
+
+ *type = 0;
+ bool writable = false;
+ bool resettable = false;
+
+ *propertyFlags = QQmlPropertyData::IsAlias;
+
+ if (alias.aliasToLocalAlias) {
+ auto targetAlias = targetObject.aliasesBegin();
+ for (uint i = 0; i < alias.localAliasIndex; ++i)
+ ++targetAlias;
+ propertyDataForAlias(component, *targetAlias, type, propertyFlags);
+ return;
+ } else if (alias.encodedMetaPropertyIndex == -1) {
+ Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
+ auto *typeRef = objectContainer->resolvedTypes.value(targetObject.inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+
+ if (typeRef->type)
+ *type = typeRef->type->typeId();
+ else
+ *type = typeRef->compilationUnit->metaTypeId;
+
+ *propertyFlags |= QQmlPropertyData::IsQObjectDerived;
+ } else {
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(alias.encodedMetaPropertyIndex, &coreIndex);
+
+ QQmlPropertyCache *targetCache = propertyCaches->at(targetObjectIndex);
+ Q_ASSERT(targetCache);
+ QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
+ Q_ASSERT(targetProperty);
+
+ *type = targetProperty->propType;
+
+ writable = targetProperty->isWritable();
+ resettable = targetProperty->isResettable();
+
+ if (valueTypeIndex != -1) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type);
+ if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
+ *type = QVariant::Int;
+ else
+ *type = valueTypeMetaObject->property(valueTypeIndex).userType();
+ } else {
+ if (targetProperty->isEnum()) {
+ *type = QVariant::Int;
+ } else {
+ // Copy type flags
+ *propertyFlags |= targetProperty->getFlags() & QQmlPropertyData::PropTypeFlagMask;
+
+ if (targetProperty->isVarProperty())
+ *propertyFlags |= QQmlPropertyData::IsQVariant;
+ }
+ }
+ }
+
+ if (!(alias.flags & QV4::CompiledData::Property::IsReadOnly) && writable)
+ *propertyFlags |= QQmlPropertyData::IsWritable;
+ else
+ *propertyFlags &= ~QQmlPropertyData::IsWritable;
+
+ if (resettable)
+ *propertyFlags |= QQmlPropertyData::IsResettable;
+ else
+ *propertyFlags &= ~QQmlPropertyData::IsResettable;
+}
+
+template <typename ObjectContainer>
+inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex)
+{
+ const CompiledObject &object = *objectContainer->objectAt(objectIndex);
+ if (!object.aliasCount())
+ return;
+
+ QQmlPropertyCache *propertyCache = propertyCaches->at(objectIndex);
+ Q_ASSERT(propertyCache);
+
+ int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.count();
+ int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
+
+ int aliasIndex = 0;
+ for (auto alias = object.aliasesBegin(), end = object.aliasesEnd(); alias != end; ++alias, ++aliasIndex) {
+ Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+
+ int type = 0;
+ quint32 propertyFlags = 0;
+ propertyDataForAlias(component, *alias, &type, &propertyFlags);
+
+ const QString propertyName = objectContainer->stringAt(alias->nameIndex);
+
+ if (object.defaultPropertyIsAlias && aliasIndex == object.indexOfDefaultPropertyOrAlias)
+ propertyCache->_defaultPropertyName = propertyName;
+
+ propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ type, effectiveSignalIndex++);
+ }
+}
+
+template <typename ObjectContainer>
+inline int QQmlPropertyCacheAliasCreator<ObjectContainer>::objectForId(const CompiledObject &component, int id) const
+{
+ 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)
+ return candidateIndex;
+ }
+ return -1;
+}
+
QT_END_NAMESPACE
#endif // QQMLPROPERTYCACHECREATOR_P_H
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 83aaba791b..bb4d603f68 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -775,7 +775,6 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
, pool(typeCompiler->memoryPool())
, qmlObjects(typeCompiler->qmlObjects())
, indexOfRootObject(typeCompiler->rootObjectIndex())
- , _componentIndex(-1)
, resolvedTypes(&typeCompiler->resolvedTypes)
, propertyCaches(std::move(typeCompiler->takePropertyCaches()))
{
@@ -924,7 +923,6 @@ bool QQmlComponentAndAliasResolver::resolve()
QmlIR::Object *component = qmlObjects->at(componentRoots.at(i));
const QmlIR::Binding *rootBinding = component->firstBinding();
- _componentIndex = i;
_idToObjectIndex.clear();
_objectsWithAliases.clear();
@@ -932,24 +930,24 @@ bool QQmlComponentAndAliasResolver::resolve()
if (!collectIdsAndAliases(rootBinding->value.objectIndex))
return false;
- if (!resolveAliases())
- return false;
-
component->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
+
+ if (!resolveAliases(componentRoots.at(i)))
+ return false;
}
// Collect ids and aliases for root
- _componentIndex = -1;
_idToObjectIndex.clear();
_objectsWithAliases.clear();
collectIdsAndAliases(indexOfRootObject);
- resolveAliases();
-
QmlIR::Object *rootComponent = qmlObjects->at(indexOfRootObject);
rootComponent->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
+ if (!resolveAliases(indexOfRootObject))
+ return false;
+
// Implicit component insertion may have added objects and thus we also need
// to extend the symmetric propertyCaches.
compiler->setPropertyCaches(std::move(propertyCaches));
@@ -991,10 +989,13 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
return true;
}
-bool QQmlComponentAndAliasResolver::resolveAliases()
+bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex)
{
if (_objectsWithAliases.isEmpty())
return true;
+
+ QQmlPropertyCacheAliasCreator<QQmlTypeCompiler> aliasCacheCreator(&propertyCaches, compiler);
+
bool atLeastOneAliasResolved;
do {
atLeastOneAliasResolved = false;
@@ -1011,7 +1012,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
}
if (result == AllAliasesResolved) {
- addAliasesToPropertyCache(objectIndex);
+ aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex);
atLeastOneAliasResolved = true;
} else if (result == SomeAliasesResolved) {
atLeastOneAliasResolved = true;
@@ -1153,113 +1154,6 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
return SomeAliasesResolved;
}
-void QQmlComponentAndAliasResolver::propertyDataForAlias(QmlIR::Alias *alias, int *type, quint32 *propertyFlags)
-{
- const auto objectForId = [this](int objectId) {
- for (auto idIt = _idToObjectIndex.constBegin(), end = _idToObjectIndex.constEnd(); idIt != end; ++idIt) {
- const QmlIR::Object *obj = qmlObjects->at(*idIt);
- if (obj->id == objectId)
- return *idIt;
- }
- return -1;
- };
-
- const int targetObjectIndex = objectForId(alias->targetObjectId);
- Q_ASSERT(targetObjectIndex >= 0);
-
- const QmlIR::Object *targetObject = qmlObjects->at(targetObjectIndex);
-
- *type = 0;
- bool writable = false;
- bool resettable = false;
-
- *propertyFlags = QQmlPropertyData::IsAlias;
-
- if (alias->aliasToLocalAlias) {
- auto targetAlias = targetObject->firstAlias();
- for (uint i = 0; i < alias->localAliasIndex; ++i)
- targetAlias = targetAlias->next;
- propertyDataForAlias(targetAlias, type, propertyFlags);
- return;
- } else if (alias->encodedMetaPropertyIndex == -1) {
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
- auto *typeRef = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
- Q_ASSERT(typeRef);
-
- if (typeRef->type)
- *type = typeRef->type->typeId();
- else
- *type = typeRef->compilationUnit->metaTypeId;
-
- *propertyFlags |= QQmlPropertyData::IsQObjectDerived;
- } else {
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(alias->encodedMetaPropertyIndex, &coreIndex);
-
- QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex);
- Q_ASSERT(targetCache);
- QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
- Q_ASSERT(targetProperty);
-
- *type = targetProperty->propType;
-
- writable = targetProperty->isWritable();
- resettable = targetProperty->isResettable();
-
- if (valueTypeIndex != -1) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type);
- if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
- *type = QVariant::Int;
- else
- *type = valueTypeMetaObject->property(valueTypeIndex).userType();
- } else {
- if (targetProperty->isEnum()) {
- *type = QVariant::Int;
- } else {
- // Copy type flags
- *propertyFlags |= targetProperty->getFlags() & QQmlPropertyData::PropTypeFlagMask;
-
- if (targetProperty->isVarProperty())
- *propertyFlags |= QQmlPropertyData::IsQVariant;
- }
- }
- }
-
- if (!(alias->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
- *propertyFlags |= QQmlPropertyData::IsWritable;
- else
- *propertyFlags &= ~QQmlPropertyData::IsWritable;
-
- if (resettable)
- *propertyFlags |= QQmlPropertyData::IsResettable;
- else
- *propertyFlags &= ~QQmlPropertyData::IsResettable;
-}
-
-void QQmlComponentAndAliasResolver::addAliasesToPropertyCache(int objectIndex)
-{
- const QmlIR::Object * const obj = qmlObjects->at(objectIndex);
- QQmlPropertyCache * const propertyCache = propertyCaches.at(objectIndex);
- Q_ASSERT(propertyCache);
- int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.count();
- int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
-
- int aliasIndex = 0;
- for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next, ++aliasIndex) {
- int type = 0;
- quint32 propertyFlags = 0;
- propertyDataForAlias(alias, &type, &propertyFlags);
-
- QString propertyName = stringAt(alias->nameIndex);
-
- if (obj->defaultPropertyIsAlias && aliasIndex == obj->indexOfDefaultPropertyOrAlias)
- propertyCache->_defaultPropertyName = propertyName;
-
- propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- type, effectiveSignalIndex++);
- }
-}
-
QQmlDeferredAndCustomParserBindingScanner::QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler)
: QQmlCompilePass(typeCompiler)
, qmlObjects(typeCompiler->qmlObjects())
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 0b078fd642..9f1a09b35c 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -265,7 +265,7 @@ public:
protected:
void findAndRegisterImplicitComponents(const QmlIR::Object *obj, QQmlPropertyCache *propertyCache);
bool collectIdsAndAliases(int objectIndex);
- bool resolveAliases();
+ bool resolveAliases(int componentIndex);
void propertyDataForAlias(QmlIR::Alias *alias, int *type, quint32 *propertyFlags);
enum AliasResolutionResult {
@@ -275,7 +275,6 @@ protected:
};
AliasResolutionResult resolveAliasesInObject(int objectIndex, QQmlCompileError *error);
- void addAliasesToPropertyCache(int objectIndex);
QQmlEnginePrivate *enginePrivate;
QQmlJS::MemoryPool *pool;
@@ -286,7 +285,6 @@ protected:
// indices of the objects that are actually Component {}
QVector<quint32> componentRoots;
- int _componentIndex;
QHash<int, int> _idToObjectIndex;
QVector<int> _objectsWithAliases;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index f1cf365b25..fc7cf4ebf1 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -565,6 +565,8 @@ struct Object
typedef TableIterator<Signal, Object, &Object::signalAt> SignalIterator;
SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
+
+ int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
// ---
};