aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp46
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h66
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp13
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h2
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp4
-rw-r--r--src/qml/qml/qqmltypedata.cpp15
-rw-r--r--src/qmltest/quicktest.cpp10
7 files changed, 105 insertions, 51 deletions
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index fa4a1f1ce4..29e1c6dbf7 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -406,9 +406,9 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
- if (typeRef->compilationUnit) {
- metaTypeId = typeRef->compilationUnit->metaTypeId;
- listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
+ if (const auto compilationUnit = typeRef->compilationUnit()) {
+ metaTypeId = compilationUnit->metaTypeId;
+ listMetaTypeId = compilationUnit->listMetaTypeId;
} else {
metaTypeId = typeRef->type.typeId();
listMetaTypeId = typeRef->type.qListTypeId();
@@ -453,17 +453,17 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
++inlineComponentData[lastICRoot].totalParserStatusCount;
++inlineComponentData[lastICRoot].totalObjectCount;
- if (typeRef->compilationUnit) {
+ if (const auto compilationUnit = typeRef->compilationUnit()) {
// if the type is an inline component type, we have to extract the information from it
// This requires that inline components are visited in the correct order
- auto icRoot = typeRef->compilationUnit->icRoot;
+ auto icRoot = compilationUnit->icRoot;
if (typeRef->type.isInlineComponentType()) {
icRoot = typeRef->type.inlineComponendId();
}
- QScopedValueRollback<int> rollback {typeRef->compilationUnit->icRoot, icRoot};
- inlineComponentData[lastICRoot].totalBindingCount += typeRef->compilationUnit->totalBindingsCount();
- inlineComponentData[lastICRoot].totalParserStatusCount += typeRef->compilationUnit->totalParserStatusCount();
- inlineComponentData[lastICRoot].totalObjectCount += typeRef->compilationUnit->totalObjectCount();
+ QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot};
+ inlineComponentData[lastICRoot].totalBindingCount += compilationUnit->totalBindingsCount();
+ inlineComponentData[lastICRoot].totalParserStatusCount += compilationUnit->totalParserStatusCount();
+ inlineComponentData[lastICRoot].totalObjectCount += compilationUnit->totalObjectCount();
}
}
}
@@ -481,15 +481,15 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
if (typeRef->type.isValid() && typeRef->type.parserStatusCast() != -1)
++parserStatusCount;
++objectCount;
- if (typeRef->compilationUnit) {
- auto icRoot = typeRef->compilationUnit->icRoot;
+ if (const auto compilationUnit = typeRef->compilationUnit()) {
+ auto icRoot = compilationUnit->icRoot;
if (typeRef->type.isInlineComponentType()) {
icRoot = typeRef->type.inlineComponendId();
}
- QScopedValueRollback<int> rollback {typeRef->compilationUnit->icRoot, icRoot};
- bindingCount += typeRef->compilationUnit->totalBindingsCount();
- parserStatusCount += typeRef->compilationUnit->totalParserStatusCount();
- objectCount += typeRef->compilationUnit->totalObjectCount();
+ QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot};
+ bindingCount += compilationUnit->totalBindingsCount();
+ parserStatusCount += compilationUnit->totalParserStatusCount();
+ objectCount += compilationUnit->totalObjectCount();
}
}
}
@@ -806,7 +806,7 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
if (type.isValid())
return typePropertyCache;
else
- return compilationUnit->rootPropertyCache();
+ return m_compilationUnit->rootPropertyCache();
}
/*!
@@ -820,8 +820,8 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQm
typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
return typePropertyCache;
} else {
- Q_ASSERT(compilationUnit);
- return compilationUnit->rootPropertyCache();
+ Q_ASSERT(m_compilationUnit);
+ return m_compilationUnit->rootPropertyCache();
}
}
@@ -832,10 +832,10 @@ bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engi
hash->addData(createPropertyCache(engine)->checksum(&ok));
return ok;
}
- if (!compilationUnit)
+ if (!m_compilationUnit)
return false;
- hash->addData(compilationUnit->data->md5Checksum,
- sizeof(compilationUnit->data->md5Checksum));
+ hash->addData(m_compilationUnit->data->md5Checksum,
+ sizeof(m_compilationUnit->data->md5Checksum));
return true;
}
@@ -856,8 +856,8 @@ void ResolvedTypeReference::doDynamicTypeCheck()
mo = typePropertyCache->firstCppMetaObject();
else if (type.isValid())
mo = type.metaObject();
- else if (compilationUnit)
- mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ else if (m_compilationUnit)
+ mo = m_compilationUnit->rootPropertyCache()->firstCppMetaObject();
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 8cad18a3dc..7bfb68da9d 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -325,27 +325,73 @@ private:
struct ResolvedTypeReference
{
+public:
ResolvedTypeReference()
- : majorVersion(0)
- , minorVersion(0)
- , isFullyDynamicType(false)
+ : m_compilationUnit(nullptr)
+ , m_stronglyReferencesCompilationUnit(true)
+ , majorVersion(0)
+ , minorVersion(0)
+ , isFullyDynamicType(false)
{}
+ ~ResolvedTypeReference()
+ {
+ if (m_stronglyReferencesCompilationUnit && m_compilationUnit)
+ m_compilationUnit->release();
+ }
+
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() { return m_compilationUnit; }
+ void setCompilationUnit(QQmlRefPointer<QV4::ExecutableCompilationUnit> unit)
+ {
+ if (m_compilationUnit == unit.data())
+ return;
+ if (m_stronglyReferencesCompilationUnit) {
+ if (m_compilationUnit)
+ m_compilationUnit->release();
+ m_compilationUnit = unit.take();
+ } else {
+ m_compilationUnit = unit.data();
+ }
+ }
+
+ bool referencesCompilationUnit() const { return m_stronglyReferencesCompilationUnit; }
+ void setReferencesCompilationUnit(bool doReference)
+ {
+ if (doReference == m_stronglyReferencesCompilationUnit)
+ return;
+ m_stronglyReferencesCompilationUnit = doReference;
+ if (!m_compilationUnit)
+ return;
+ if (doReference) {
+ m_compilationUnit->addref();
+ } else if (m_compilationUnit->count() == 1) {
+ m_compilationUnit->release();
+ m_compilationUnit = nullptr;
+ } else {
+ m_compilationUnit->release();
+ }
+ }
+
+ QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
+ QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+
+ void doDynamicTypeCheck();
+
QQmlType type;
QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
+private:
+ Q_DISABLE_COPY_MOVE(ResolvedTypeReference)
+
+ QV4::ExecutableCompilationUnit *m_compilationUnit;
+ bool m_stronglyReferencesCompilationUnit;
+public:
int majorVersion;
int minorVersion;
// Types such as QQmlPropertyMap can add properties dynamically at run-time and
// therefore cannot have a property cache installed when instantiated.
bool isFullyDynamicType;
-
- QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
- QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
-
- void doDynamicTypeCheck();
};
IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 76f387bbdc..3ca89924f9 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -1214,11 +1214,12 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
- Q_ASSERT(typeRef->compilationUnit);
- typeName = typeRef->compilationUnit->fileName();
+ const auto compilationUnit = typeRef->compilationUnit();
+ Q_ASSERT(compilationUnit);
+ typeName = compilationUnit->fileName();
// compilation unit is shared between root type and its inline component types
// so isSingleton errorneously returns true for inline components
- if (typeRef->compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType())
+ if (compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
return nullptr;
@@ -1226,7 +1227,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (!type.isInlineComponentType()) {
- QQmlObjectCreator subCreator(context, typeRef->compilationUnit, sharedState.data());
+ QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
instance = subCreator.create();
if (!instance) {
errors += subCreator.errors;
@@ -1234,8 +1235,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
}
} else {
int subObjectId = type.inlineComponendId();
- QScopedValueRollback<int> rollback {typeRef->compilationUnit->icRoot, subObjectId};
- QQmlObjectCreator subCreator(context, typeRef->compilationUnit, sharedState.data());
+ QScopedValueRollback<int> rollback {compilationUnit->icRoot, subObjectId};
+ QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
instance = subCreator.create(subObjectId, nullptr, nullptr, CreationFlags::InlineComponent);
if (!instance) {
errors += subCreator.errors;
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index 5669f9e13d..6b02d6fb98 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -840,7 +840,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
if (typeRef->type.isValid())
*type = typeRef->type.typeId();
else
- *type = typeRef->compilationUnit->metaTypeId;
+ *type = typeRef->compilationUnit()->metaTypeId;
*minorVersion = typeRef->minorVersion;
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index f4737ba99d..058bf8848c 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -813,8 +813,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
const QMetaObject *firstMetaObject = nullptr;
if (tr->type.isValid())
firstMetaObject = tr->type.metaObject();
- else if (tr->compilationUnit)
- firstMetaObject = tr->compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ else if (const auto compilationUnit = tr->compilationUnit())
+ firstMetaObject = compilationUnit->rootPropertyCache()->firstCppMetaObject();
if (isUsableComponent(firstMetaObject))
continue;
// if here, not a QQmlComponent, so needs wrapping
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index cd4e0acf39..fc1d0cfbcf 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -300,7 +300,14 @@ void QQmlTypeData::setCompileUnit(const Container &container)
auto const root = container->objectAt(i);
for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
auto *typeRef = m_compiledData->resolvedType(it->nameIndex);
- typeRef->compilationUnit = m_compiledData; // share compilation unit
+
+ // We don't want the type reference to keep a strong reference to the compilation unit
+ // here. The compilation unit owns the type reference, and having a strong reference
+ // would prevent the compilation unit from ever getting deleted. We can still be sure
+ // that the compilation unit outlives the type reference, due to ownership.
+ typeRef->setReferencesCompilationUnit(false);
+
+ typeRef->setCompilationUnit(m_compiledData); // share compilation unit
}
}
}
@@ -919,7 +926,7 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) {
return qQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName()));
}
- ref->compilationUnit = resolvedType->typeData->compilationUnit();
+ ref->setCompilationUnit(resolvedType->typeData->compilationUnit());
if (resolvedType->type.isInlineComponentType()) {
// Inline component which is part of an already resolved type
int objectId = -1;
@@ -943,12 +950,12 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
auto typeID = qmlType.lookupInlineComponentById(qmlType.inlineComponendId()).typeId();
auto exUnit = engine->obtainExecutableCompilationUnit(typeID);
if (exUnit) {
- ref->compilationUnit = exUnit;
+ ref->setCompilationUnit(exUnit);
ref->typePropertyCache = engine->propertyCacheForType(typeID);
}
}
} else {
- ref->compilationUnit = m_inlineComponentToCompiledData[resolvedType.key()];
+ ref->setCompilationUnit(m_inlineComponentToCompiledData[resolvedType.key()]);
ref->typePropertyCache = m_inlineComponentToCompiledData[resolvedType.key()]->rootPropertyCache();
}
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 470b3c0f7a..443496c9bc 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -332,8 +332,9 @@ private:
}
};
- TestCaseEnumerationResult enumerateTestCases(QV4::ExecutableCompilationUnit *compilationUnit,
- const Object *object = nullptr)
+ TestCaseEnumerationResult enumerateTestCases(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const Object *object = nullptr)
{
QQmlType testCaseType;
for (quint32 i = 0, count = compilationUnit->importCount(); i < count; ++i) {
@@ -356,9 +357,8 @@ private:
if (!object) // Start at root of compilation unit if not enumerating a specific child
object = compilationUnit->objectAt(0);
- if (QV4::ExecutableCompilationUnit *superTypeUnit
- = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)
- ->compilationUnit.data()) {
+ if (const auto superTypeUnit = compilationUnit->resolvedTypes.value(
+ object->inheritedTypeNameIndex)->compilationUnit()) {
// We have a non-C++ super type, which could indicate we're a subtype of a TestCase
if (testCaseType.isValid() && superTypeUnit->url() == testCaseType.sourceUrl())
result.isTestCase = true;