From a91b83c0bbafbdfb290f2766d51d12e805506e30 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Mar 2017 16:55:13 +0100 Subject: Clean up type dependency hashing for QML caching Instead of passing the engine parameter all the way through the data structure generator, along with the dependent type data structure that is unused otherwise, let's simply provide a function object for the dependency hashing. This is also in preparation for adding singleton types to the dependency hash. Task-number: QTBUG-58486 Change-Id: I5bb5e5c06b7b5c77195cec3da13141333cfea7a8 Reviewed-by: Lars Knoll --- src/qml/qml/qqmltypeloader.cpp | 16 ++++++++++------ src/qml/qml/qqmltypeloader_p.h | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 7ad18c8efb..dea8f3ed6f 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2227,8 +2227,12 @@ void QQmlTypeData::done() QQmlEngine *const engine = typeLoader()->engine(); + const auto dependencyHasher = [engine, resolvedTypeCache](QCryptographicHash *hash) { + return resolvedTypeCache.addToHash(hash, engine); + }; + // verify if any dependencies changed if we're using a cache - if (m_document.isNull() && !m_compiledData->verifyChecksum(engine, resolvedTypeCache)) { + if (m_document.isNull() && !m_compiledData->verifyChecksum(dependencyHasher)) { qCDebug(DBG_DISK_CACHE) << "Checksum mismatch for cached version of" << m_compiledData->url().toString(); if (!loadFromSource()) return; @@ -2238,7 +2242,7 @@ void QQmlTypeData::done() if (!m_document.isNull()) { // Compile component - compile(importCache, resolvedTypeCache); + compile(importCache, resolvedTypeCache, dependencyHasher); } else { createTypeAndPropertyCaches(importCache, resolvedTypeCache); } @@ -2487,12 +2491,13 @@ QString QQmlTypeData::stringAt(int index) const return m_document->jsGenerator.stringTable.stringForIndex(index); } -void QQmlTypeData::compile(const QQmlRefPointer &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) +void QQmlTypeData::compile(const QQmlRefPointer &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache, + const QV4::CompiledData::DependentTypesHasher &dependencyHasher) { Q_ASSERT(m_compiledData.isNull()); QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine()); - QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), importCache, resolvedTypeCache); + QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), importCache, resolvedTypeCache, dependencyHasher); m_compiledData = compiler.compile(); if (!m_compiledData) { setError(compiler.compilationErrors()); @@ -2934,8 +2939,7 @@ void QQmlScriptBlob::dataReceived(const Data &data) irUnit.jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; QmlIR::QmlUnitGenerator qmlGenerator; - QV4::CompiledData::ResolvedTypeReferenceMap emptyDependencies; - QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit, m_typeLoader->engine(), emptyDependencies); + QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit); Q_ASSERT(!unit->data); // The js unit owns the data and will free the qml unit. unit->data = unitData; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 53cf4234e1..d85346c23e 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -453,7 +453,7 @@ private: QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache ) const; void compile(const QQmlRefPointer &importCache, - const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); + const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); void createTypeAndPropertyCaches(const QQmlRefPointer &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref); -- cgit v1.2.3 From 5b94de09cc738837d1539e28b3c0dccd17c18d29 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Mar 2017 15:24:59 +0100 Subject: Fix caching of QML singleton types When a QML file depends on a QML singleton, we failed to include it in the dependency hash. Thus changes to the QML singleton did not result in a re-creation of the caches of files that use it. The list of singletons comes from random-ordered hashes in the qml import handling. We provide an order to the direct dependencies by sorting by the singleton type names. Task-number: QTBUG-58486 Change-Id: Ie7e9d006f9bf3a60af1f819ee439c29bc234bd8a Reviewed-by: Lars Knoll --- src/qml/qml/qqmltypeloader.cpp | 37 +++++++++++++++++++++++++++++++++++-- src/qml/qml/qqmltypeloader_p.h | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index dea8f3ed6f..3004fd2196 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2007,6 +2007,16 @@ QQmlTypeData::TypeDataCallback::~TypeDataCallback() { } +QString QQmlTypeData::TypeReference::qualifiedName() const +{ + QString result; + if (!prefix.isEmpty()) { + result = prefix + QLatin1Char('.'); + } + result.append(type->qmlTypeName()); + return result; +} + QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager) : QQmlTypeLoader::Blob(url, QmlFile, manager), m_typesResolved(false), m_implicitImportLoaded(false) @@ -2147,6 +2157,23 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer &typeRefs, QCryptographicHash *hash, QQmlEngine *engine) +{ + for (const auto &typeRef: typeRefs) { + if (typeRef.typeData) { + const auto unit = typeRef.typeData->compilationUnit(); + hash->addData(unit->data->md5Checksum, sizeof(unit->data->md5Checksum)); + } else if (typeRef.type) { + const auto propertyCache = QQmlEnginePrivate::get(engine)->cache(typeRef.type->metaObject()); + bool ok = false; + hash->addData(propertyCache->checksum(&ok)); + if (!ok) + return false; + } + } + return true; +} + void QQmlTypeData::done() { QDeferredCleanup cleanup([this]{ @@ -2227,8 +2254,10 @@ void QQmlTypeData::done() QQmlEngine *const engine = typeLoader()->engine(); - const auto dependencyHasher = [engine, resolvedTypeCache](QCryptographicHash *hash) { - return resolvedTypeCache.addToHash(hash, engine); + const auto dependencyHasher = [engine, resolvedTypeCache, this](QCryptographicHash *hash) { + if (!resolvedTypeCache.addToHash(hash, engine)) + return false; + return ::addTypeReferenceChecksumsToHash(m_compositeSingletons, hash, engine); }; // verify if any dependencies changed if we're using a cache @@ -2568,6 +2597,10 @@ void QQmlTypeData::resolveTypes() } } + std::stable_sort(m_compositeSingletons.begin(), m_compositeSingletons.end(), [](const TypeReference &lhs, const TypeReference &rhs){ + return lhs.qualifiedName() < rhs.qualifiedName(); + }); + for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_typeReferences.constBegin(), end = m_typeReferences.constEnd(); unresolvedRef != end; ++unresolvedRef) { diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index d85346c23e..e3c4a52c45 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -400,6 +400,7 @@ public: int minorVersion; QQmlTypeData *typeData; QString prefix; // used by CompositeSingleton types + QString qualifiedName() const; bool needsCreation; }; -- cgit v1.2.3 From 5adfb4063a64aa3ae27269330c1fb8960dda4082 Mon Sep 17 00:00:00 2001 From: Josh Faust Date: Tue, 23 Apr 2013 21:36:30 -0700 Subject: Fix QQmlTypeLoader::Blob::qmldirDataAvailable memory overwrite An invalid iterator was being dereferenced. Task-number: QTBUG-59268 Change-Id: I58635667ab4591c06f1d7644243b83fd0172e74f Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypeloader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 3004fd2196..6465cd0b19 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1527,7 +1527,8 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList