From c225e23e00bc539daefa357f687fe4a1b51ade9f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 8 Jan 2024 12:56:38 +0100 Subject: [PATCH] QtQml: Move ResolvedTypeReference into base CU Change-Id: I25063457aad3a6d29a8c2a5b236f9a51b56a2f51 Reviewed-by: Fabian Kosmale --- src/qml/common/qv4compileddata.cpp | 55 ++++++++++++++++++- src/qml/common/qv4compileddata_p.h | 30 +++++----- .../qv4executablecompilationunit.cpp | 41 +------------- .../qv4executablecompilationunit_p.h | 24 +++++--- src/qml/qml/qqmltypecompiler.cpp | 2 +- src/qml/qml/qqmltypecompiler_p.h | 4 +- src/qml/qml/qqmltypedata.cpp | 14 ++--- src/qml/qml/qqmltypedata_p.h | 9 +-- src/qmltest/quicktest.cpp | 4 +- 9 files changed, 103 insertions(+), 80 deletions(-) diff --git a/src/qml/common/qv4compileddata.cpp b/src/qml/common/qv4compileddata.cpp index 14315084bd..16ef43f678 100644 --- a/src/qml/common/qv4compileddata.cpp +++ b/src/qml/common/qv4compileddata.cpp @@ -3,9 +3,10 @@ #include "qv4compileddata_p.h" +#include + #include -#include #include #include #include @@ -15,6 +16,48 @@ QT_BEGIN_NAMESPACE namespace QV4 { namespace CompiledData { +/*! + \internal + This function creates a temporary key vector and sorts it to guarantuee a stable + hash. This is used to calculate a check-sum on dependent meta-objects. + */ +bool ResolvedTypeReferenceMap::addToHash( + QCryptographicHash *hash, QHash *checksums) const +{ + std::vector keys (size()); + int i = 0; + for (auto it = constBegin(), end = constEnd(); it != end; ++it) { + keys[i] = it.key(); + ++i; + } + std::sort(keys.begin(), keys.end()); + for (int key: keys) { + if (!this->operator[](key)->addToHash(hash, checksums)) + return false; + } + + return true; +} + +CompilationUnit::~CompilationUnit() +{ + qDeleteAll(resolvedTypes); + + if (data) { + if (data->qmlUnit() != qmlData) + free(const_cast(qmlData)); + qmlData = nullptr; + + if (!(data->flags & QV4::CompiledData::Unit::StaticData)) + free(const_cast(data)); + } + data = nullptr; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + delete [] constants; + constants = nullptr; +#endif +} + QString CompilationUnit::localCacheFilePath(const QUrl &url) { static const QByteArray envCachePath = qgetenv("QML_DISK_CACHE_PATH"); @@ -117,6 +160,16 @@ QStringList CompilationUnit::moduleRequests() const return requests; } +ResolvedTypeReference *CompilationUnit::resolvedType(QMetaType type) const +{ + for (ResolvedTypeReference *ref : std::as_const(resolvedTypes)) { + if (ref->type().typeId() == type) + return ref; + } + return nullptr; + +} + } // namespace CompiledData } // namespace QV4 diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index d9268c8407..0adac2874c 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -74,12 +75,19 @@ struct InternalClass; struct Function; class EvalISelFactory; +class ResolvedTypeReference; namespace CompiledData { // index is per-object binding index using BindingPropertyData = QVector; +// map from name index +struct ResolvedTypeReferenceMap: public QHash +{ + bool addToHash(QCryptographicHash *hash, QHash *checksums) const; +}; + struct String; struct Function; struct Lookup; @@ -1473,6 +1481,8 @@ struct CompilationUnit final : public QQmlRefCounted // lookups by string (property name). QVector bindingPropertyDataPerObject; + ResolvedTypeReferenceMap resolvedTypes; + public: using CompiledObject = CompiledData::Object; @@ -1489,22 +1499,7 @@ public: this->aotCompiledFunctions = aotCompiledFunctions; } - ~CompilationUnit() - { - if (data) { - if (data->qmlUnit() != qmlData) - free(const_cast(qmlData)); - qmlData = nullptr; - - if (!(data->flags & QV4::CompiledData::Unit::StaticData)) - free(const_cast(data)); - } - data = nullptr; -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - delete [] constants; - constants = nullptr; -#endif - } + Q_QML_EXPORT ~CompilationUnit(); const Unit *unitData() const { return data; } @@ -1620,6 +1615,9 @@ public: return m_finalUrl; } + ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } + ResolvedTypeReference *resolvedType(QMetaType type) const; + private: QString m_fileName; // initialized from data->sourceFileIndex QString m_finalUrlString; // initialized from data->finalUrlIndex diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index 14444c6ed4..ffd8b787e1 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -268,9 +268,6 @@ void ExecutableCompilationUnit::clear() typeNameCache.reset(); - qDeleteAll(resolvedTypes); - resolvedTypes.clear(); - delete [] runtimeLookups; runtimeLookups = nullptr; @@ -391,7 +388,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(const QQmlType &type) QQmlMetaType::registerInternalCompositeType(this); } else { const QV4::CompiledData::Object *obj = objectAt(/*root object*/0); - auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); + auto *typeRef = m_compilationUnit->resolvedTypes.value(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); if (const auto compilationUnit = typeRef->compilationUnit()) qmlType = compilationUnit->qmlType; @@ -435,7 +432,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(const QQmlType &type) m_compilationUnit->inlineComponentData[lastICRootName].totalBindingCount += obj->nBindings; - if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { + if (auto *typeRef = m_compilationUnit->resolvedTypes.value(obj->inheritedTypeNameIndex)) { const auto type = typeRef->type(); if (type.isValid() && type.parserStatusCast() != -1) ++m_compilationUnit->inlineComponentData[lastICRootName].totalParserStatusCount; @@ -463,7 +460,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(const QQmlType &type) continue; bindingCount += obj->nBindings; - if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { + if (auto *typeRef = m_compilationUnit->resolvedTypes.value(obj->inheritedTypeNameIndex)) { const auto type = typeRef->type(); if (type.isValid() && type.parserStatusCast() != -1) ++parserStatusCount; @@ -495,15 +492,6 @@ int ExecutableCompilationUnit::totalObjectCount() const { return m_compilationUnit->inlineComponentData[*icRootName()].totalObjectCount; } -ResolvedTypeReference *ExecutableCompilationUnit::resolvedType(QMetaType type) const -{ - for (ResolvedTypeReference *ref : std::as_const(resolvedTypes)) { - if (ref->type().typeId() == type) - return ref; - } - return nullptr; -} - int ExecutableCompilationUnit::totalParserStatusCount() const { if (!m_compilationUnit->icRootName) return m_totalParserStatusCount; @@ -854,29 +842,6 @@ void ExecutableCompilationUnit::evaluateModuleRequests() } } -/*! - \internal - This function creates a temporary key vector and sorts it to guarantuee a stable - hash. This is used to calculate a check-sum on dependent meta-objects. - */ -bool ResolvedTypeReferenceMap::addToHash( - QCryptographicHash *hash, QHash *checksums) const -{ - std::vector keys (size()); - int i = 0; - for (auto it = constBegin(), end = constEnd(); it != end; ++it) { - keys[i] = it.key(); - ++i; - } - std::sort(keys.begin(), keys.end()); - for (int key: keys) { - if (!this->operator[](key)->addToHash(hash, checksums)) - return false; - } - - return true; -} - QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const { #if QT_CONFIG(translation) diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 11adcb79cd..d1504079b4 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -34,12 +34,6 @@ class QQmlEnginePrivate; namespace QV4 { class CompilationUnitMapper; -class ResolvedTypeReference; -// map from name index -struct ResolvedTypeReferenceMap: public QHash -{ - bool addToHash(QCryptographicHash *hash, QHash *checksums) const; -}; struct CompilationUnitRuntimeData { @@ -113,9 +107,21 @@ public: int totalObjectCount() const; QVector> dependentScripts; - ResolvedTypeReferenceMap resolvedTypes; - ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } - ResolvedTypeReference *resolvedType(QMetaType type) const; + + ResolvedTypeReference *resolvedType(int id) const + { + return m_compilationUnit->resolvedType(id); + } + + ResolvedTypeReference *resolvedType(QMetaType type) const + { + return m_compilationUnit->resolvedType(type); + } + + void setResolvedTypes(const CompiledData::ResolvedTypeReferenceMap &resolvedTypes) + { + m_compilationUnit->resolvedTypes = resolvedTypes; + } bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const; diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index 243a9ee412..eb07ebc223 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -26,7 +26,7 @@ Q_LOGGING_CATEGORY(lcQmlTypeCompiler, "qt.qml.typecompiler"); QQmlTypeCompiler::QQmlTypeCompiler( QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *parsedQML, - QV4::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) : resolvedTypes(resolvedTypeCache) , engine(engine) diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h index aba3b45d43..6d9e5a77ca 100644 --- a/src/qml/qml/qqmltypecompiler_p.h +++ b/src/qml/qml/qqmltypecompiler_p.h @@ -46,7 +46,7 @@ public: QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, - QV4::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); // --- interface used by QQmlPropertyCacheCreator @@ -63,7 +63,7 @@ public: QString stringAt(int idx) const; QmlIR::PoolList::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); } QmlIR::PoolList::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); } - QV4::ResolvedTypeReferenceMap *resolvedTypes = nullptr; + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr; ListPropertyAssignBehavior listPropertyAssignBehavior() const { for (const QmlIR::Pragma *pragma: document->pragmas) { diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index 54a515177e..b0d1b82829 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -236,11 +236,11 @@ bool QQmlComponentAndAliasResolver::wrapImplicit QQmlError QQmlTypeData::createTypeAndPropertyCaches( const QQmlRefPointer &typeNameCache, - const QV4::ResolvedTypeReferenceMap &resolvedTypeCache) + const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) { Q_ASSERT(m_compiledData); m_compiledData->typeNameCache = typeNameCache; - m_compiledData->resolvedTypes = resolvedTypeCache; + m_compiledData->setResolvedTypes(resolvedTypeCache); m_compiledData->setInlineComponentData(m_inlineComponentData); QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine()); @@ -440,7 +440,7 @@ void QQmlTypeData::done() else setupICs(m_compiledData, &m_inlineComponentData, finalUrl(), m_compiledData); - QV4::ResolvedTypeReferenceMap resolvedTypeCache; + QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache; QQmlRefPointer typeNameCache; { QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); @@ -482,7 +482,7 @@ void QQmlTypeData::done() return; // We want to keep our resolve types ... - m_compiledData->resolvedTypes.clear(); + m_compiledData->setResolvedTypes({}); // ... but we don't want the property caches we've created for the broken CU. for (QV4::ResolvedTypeReference *ref: std::as_const(resolvedTypeCache)) { const auto compilationUnit = ref->compilationUnit(); @@ -808,7 +808,7 @@ QString QQmlTypeData::stringAt(int index) const } void QQmlTypeData::compile(const QQmlRefPointer &typeNameCache, - QV4::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) { Q_ASSERT(m_compiledData.isNull()); @@ -847,7 +847,7 @@ void QQmlTypeData::compile(const QQmlRefPointer &typeNameCach m_compiledData = enginePrivate->v4engine()->executableCompilationUnit( std::move(compilationUnit)); m_compiledData->typeNameCache = typeNameCache; - m_compiledData->resolvedTypes = *resolvedTypeCache; + m_compiledData->setResolvedTypes(*resolvedTypeCache); m_compiledData->propertyCaches = std::move(*compiler.propertyCaches()); Q_ASSERT(m_compiledData->propertyCaches.count() == static_cast(m_compiledData->objectCount())); @@ -958,7 +958,7 @@ void QQmlTypeData::resolveTypes() QQmlError QQmlTypeData::buildTypeResolutionCaches( QQmlRefPointer *typeNameCache, - QV4::ResolvedTypeReferenceMap *resolvedTypeCache) const + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache) const { typeNameCache->adopt(new QQmlTypeNameCache(m_importCache)); diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h index fafb7e4448..57749d50cf 100644 --- a/src/qml/qml/qqmltypedata_p.h +++ b/src/qml/qml/qqmltypedata_p.h @@ -92,13 +92,14 @@ private: void resolveTypes(); QQmlError buildTypeResolutionCaches( QQmlRefPointer *typeNameCache, - QV4::ResolvedTypeReferenceMap *resolvedTypeCache + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache ) const; void compile(const QQmlRefPointer &typeNameCache, - QV4::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); - QQmlError createTypeAndPropertyCaches(const QQmlRefPointer &typeNameCache, - const QV4::ResolvedTypeReferenceMap &resolvedTypeCache); + QQmlError createTypeAndPropertyCaches( + const QQmlRefPointer &typeNameCache, + const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); bool resolveType(const QString &typeName, QTypeRevision &version, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true, diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 76f823a301..d15dd638b0 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -367,8 +367,8 @@ private: if (object->hasFlag(Object::IsInlineComponentRoot)) return result; - if (const auto superTypeUnit = compilationUnit->resolvedTypes.value( - object->inheritedTypeNameIndex)->compilationUnit()) { + if (const auto superTypeUnit = compilationUnit->resolvedType(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;