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-14 13:26:23 +0100
commitf73fb997f216797c2a79101fd8aa8cb257ec7eba (patch)
tree754ac36236a90f303081ed629118d2eddd03982b
parent3f352c5cccf410cc8e9233c209d1e7f57ff1c9db (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. Task-number: QTBUG-73271 Change-Id: I7bea65e73769f76352bb5947d7229e256e7f2f25 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit a2184b9ab7469bc5ca36478394243a04cda9006c) Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp5
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h3
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference.cpp5
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference_p.h3
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp24
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h3
-rw-r--r--src/qml/qml/qqmltypedata.cpp12
-rw-r--r--src/qml/qml/qqmltypeloader.cpp1
-rw-r--r--src/qml/qml/qqmltypeloader_p.h4
9 files changed, 39 insertions, 21 deletions
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 68e2787cc0..eee826e87e 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -860,7 +860,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, QQmlEngine *engine) const
+bool ResolvedTypeReferenceMap::addToHash(
+ QCryptographicHash *hash, QQmlEngine *engine, QHash<quintptr, QByteArray> *checksums) const
{
std::vector<int> keys (count());
int i = 0;
@@ -870,7 +871,7 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *e
}
std::sort(keys.begin(), keys.end());
for (int key: keys) {
- if (!this->operator[](key)->addToHash(hash, engine))
+ if (!this->operator[](key)->addToHash(hash, engine, checksums))
return false;
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index e4670553cb..48fd339a4e 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -94,7 +94,8 @@ class ResolvedTypeReference;
// map from name index
struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*>
{
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine,
+ 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 d81f512391..e78a1d3244 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference.cpp
+++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp
@@ -96,11 +96,12 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQm
}
}
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
+bool ResolvedTypeReference::addToHash(
+ QCryptographicHash *hash, QQmlEngine *engine, QHash<quintptr, QByteArray> *checksums)
{
if (m_type.isValid() && !m_type.isInlineComponentType()) {
bool ok = false;
- hash->addData(createPropertyCache(engine)->checksum(&ok));
+ hash->addData(createPropertyCache(engine)->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 7e8bedad62..ce13e3afcb 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference_p.h
+++ b/src/qml/jsruntime/qv4resolvedtypereference_p.h
@@ -75,7 +75,8 @@ public:
QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine, QHash<quintptr,
+ QByteArray> *checksums);
void doDynamicTypeCheck();
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 9b01b2d8fb..191944b2d5 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -1259,35 +1259,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 46ecd0b5d2..2e3368ebaa 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -244,7 +244,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; }
@@ -330,7 +330,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 89bccc0c39..51564e2429 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -252,7 +252,10 @@ void QQmlTypeData::createTypeAndPropertyCaches(
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
}
-static bool addTypeReferenceChecksumsToHash(const QList<QQmlTypeData::TypeReference> &typeRefs, QCryptographicHash *hash, QQmlEngine *engine)
+static bool addTypeReferenceChecksumsToHash(
+ const QList<QQmlTypeData::TypeReference> &typeRefs,
+ QCryptographicHash *hash, QQmlEngine *engine,
+ QHash<quintptr, QByteArray> *checksums)
{
for (const auto &typeRef: typeRefs) {
if (typeRef.typeData) {
@@ -261,7 +264,7 @@ static bool addTypeReferenceChecksumsToHash(const QList<QQmlTypeData::TypeRefere
} else if (typeRef.type.isValid()) {
const auto propertyCache = QQmlEnginePrivate::get(engine)->cache(typeRef.type.metaObject());
bool ok = false;
- hash->addData(propertyCache->checksum(&ok));
+ hash->addData(propertyCache->checksum(checksums, &ok));
if (!ok)
return false;
}
@@ -421,8 +424,9 @@ void QQmlTypeData::done()
const auto dependencyHasher = [engine, &resolvedTypeCache, this]() {
QCryptographicHash hash(QCryptographicHash::Md5);
- return (resolvedTypeCache.addToHash(&hash, engine)
- && ::addTypeReferenceChecksumsToHash(m_compositeSingletons, &hash, engine))
+ return (resolvedTypeCache.addToHash(&hash, engine, typeLoader()->checksumCache())
+ && ::addTypeReferenceChecksumsToHash(m_compositeSingletons, &hash, engine,
+ typeLoader()->checksumCache()))
? 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);