aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-03-04 14:56:36 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-03-09 12:40:06 +0100
commita2184b9ab7469bc5ca36478394243a04cda9006c (patch)
tree7b454b7387b6f390433858af5fcca82ed470c6e4
parent579013497bb23b2014e2c940c3d2d1dd10847e07 (diff)
QQmlPropertyCache: Store checksums in type loader
The type loader is specific to the engine. This way we can calculate/retrieve the checksum without modifying the property cache, which makes checksum() threadsafe. The checksums are only needed for loading and storing compilation units from/to disk. Therefore, there is no point in keeping them inside the property caches anyway. Pick-to: 6.3 Task-number: QTBUG-73271 Change-Id: I7bea65e73769f76352bb5947d7229e256e7f2f25 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp5
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h2
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference.cpp5
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference_p.h2
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp24
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h3
-rw-r--r--src/qml/qml/qqmltypedata.cpp10
-rw-r--r--src/qml/qml/qqmltypeloader.cpp1
-rw-r--r--src/qml/qml/qqmltypeloader_p.h4
9 files changed, 35 insertions, 21 deletions
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 7c02391a1a..6e0d07210c 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -858,7 +858,8 @@ bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorSt
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) const
+bool ResolvedTypeReferenceMap::addToHash(
+ QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const
{
std::vector<int> keys (count());
int i = 0;
@@ -868,7 +869,7 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash) const
}
std::sort(keys.begin(), keys.end());
for (int key: keys) {
- if (!this->operator[](key)->addToHash(hash))
+ if (!this->operator[](key)->addToHash(hash, checksums))
return false;
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 6798829898..c093033aab 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -94,7 +94,7 @@ class ResolvedTypeReference;
// map from name index
struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*>
{
- bool addToHash(QCryptographicHash *hash) const;
+ bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
};
class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit,
diff --git a/src/qml/jsruntime/qv4resolvedtypereference.cpp b/src/qml/jsruntime/qv4resolvedtypereference.cpp
index 96bddccf83..4ac68611f4 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference.cpp
+++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp
@@ -100,11 +100,12 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache()
}
}
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash)
+bool ResolvedTypeReference::addToHash(
+ QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
{
if (m_type.isValid() && !m_type.isInlineComponentType()) {
bool ok = false;
- hash->addData(createPropertyCache()->checksum(&ok));
+ hash->addData(createPropertyCache()->checksum(checksums, &ok));
return ok;
}
if (!m_compilationUnit)
diff --git a/src/qml/jsruntime/qv4resolvedtypereference_p.h b/src/qml/jsruntime/qv4resolvedtypereference_p.h
index 61e683ce17..582c3a5d0a 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference_p.h
+++ b/src/qml/jsruntime/qv4resolvedtypereference_p.h
@@ -75,7 +75,7 @@ public:
QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
QQmlRefPointer<QQmlPropertyCache> createPropertyCache();
- bool addToHash(QCryptographicHash *hash);
+ bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums);
void doDynamicTypeCheck();
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 66e83c1655..035098d4c5 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -1256,35 +1256,41 @@ bool QQmlPropertyCache::addToHash(QCryptographicHash &hash, const QMetaObject &m
return true;
}
-QByteArray QQmlPropertyCache::checksum(bool *ok)
+QByteArray QQmlPropertyCache::checksum(QHash<quintptr, QByteArray> *checksums, bool *ok) const
{
- if (!_checksum.isEmpty()) {
+ auto it = checksums->constFind(quintptr(this));
+ if (it != checksums->constEnd()) {
*ok = true;
- return _checksum;
+ return *it;
}
// Generate a checksum on the meta-object data only on C++ types.
if (!_metaObject || _metaObject.isShared()) {
*ok = false;
- return _checksum;
+ return QByteArray();
}
QCryptographicHash hash(QCryptographicHash::Md5);
if (_parent) {
- hash.addData(_parent->checksum(ok));
+ hash.addData(_parent->checksum(checksums, ok));
if (!*ok)
return QByteArray();
}
- if (!addToHash(hash, *createMetaObject())) {
+ if (!addToHash(hash, *_metaObject)) {
*ok = false;
return QByteArray();
}
- _checksum = hash.result();
- *ok = !_checksum.isEmpty();
- return _checksum;
+ const QByteArray result = hash.result();
+ if (result.isEmpty()) {
+ *ok = false;
+ } else {
+ *ok = true;
+ checksums->insert(quintptr(this), result);
+ }
+ return result;
}
/*! \internal
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 68830ba716..4c10de7823 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -247,7 +247,7 @@ public:
static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
- QByteArray checksum(bool *ok);
+ QByteArray checksum(QHash<quintptr, QByteArray> *checksums, bool *ok) const;
QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; }
void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; }
@@ -333,7 +333,6 @@ private:
QByteArray _listPropertyAssignBehavior;
QString _defaultPropertyName;
QQmlPropertyCacheMethodArguments *argumentsCache = nullptr;
- QByteArray _checksum;
int methodIndexCacheStart = 0;
int signalHandlerIndexCacheStart = 0;
int _jsFactoryMethodIndex = -1;
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index aa3be1cabf..448bae3cc5 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -253,7 +253,8 @@ void QQmlTypeData::createTypeAndPropertyCaches(
}
static bool addTypeReferenceChecksumsToHash(
- const QList<QQmlTypeData::TypeReference> &typeRefs, QCryptographicHash *hash)
+ const QList<QQmlTypeData::TypeReference> &typeRefs,
+ QHash<quintptr, QByteArray> *checksums, QCryptographicHash *hash)
{
for (const auto &typeRef: typeRefs) {
if (typeRef.typeData) {
@@ -262,7 +263,7 @@ static bool addTypeReferenceChecksumsToHash(
} else if (typeRef.type.isValid()) {
const auto propertyCache = QQmlMetaType::propertyCache(typeRef.type.metaObject());
bool ok = false;
- hash->addData(propertyCache->checksum(&ok));
+ hash->addData(propertyCache->checksum(checksums, &ok));
if (!ok)
return false;
}
@@ -420,8 +421,9 @@ void QQmlTypeData::done()
const auto dependencyHasher = [&resolvedTypeCache, this]() {
QCryptographicHash hash(QCryptographicHash::Md5);
- return (resolvedTypeCache.addToHash(&hash)
- && ::addTypeReferenceChecksumsToHash(m_compositeSingletons, &hash))
+ return (resolvedTypeCache.addToHash(&hash, typeLoader()->checksumCache())
+ && ::addTypeReferenceChecksumsToHash(
+ m_compositeSingletons, typeLoader()->checksumCache(), &hash))
? hash.result()
: QByteArray();
};
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 59c9f858f6..b41f15a7c2 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1220,6 +1220,7 @@ void QQmlTypeLoader::clearCache()
m_qmldirCache.clear();
m_importDirCache.clear();
m_importQmlDirCache.clear();
+ m_checksumCache.clear();
QQmlMetaType::freeUnusedTypesAndCaches();
}
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index eb6e549911..10f96df735 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -78,6 +78,7 @@ class Q_QML_PRIVATE_EXPORT QQmlTypeLoader
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
public:
+ using ChecksumCache = QHash<quintptr, QByteArray>;
enum Mode { PreferSynchronous, Asynchronous, Synchronous };
class Q_QML_PRIVATE_EXPORT Blob : public QQmlDataBlob
@@ -141,6 +142,8 @@ public:
~QQmlTypeLoader();
QQmlImportDatabase *importDatabase() const;
+ ChecksumCache *checksumCache() { return &m_checksumCache; }
+ const ChecksumCache *checksumCache() const { return &m_checksumCache; }
static QUrl normalize(const QUrl &unNormalizedUrl);
@@ -247,6 +250,7 @@ private:
QmldirCache m_qmldirCache;
ImportDirCache m_importDirCache;
ImportQmlDirCache m_importQmlDirCache;
+ ChecksumCache m_checksumCache;
template<typename Loader>
void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode);