aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2016-07-28 17:40:32 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2016-08-02 07:22:26 +0000
commit54ee6994e66936c1d532f7718c858c9b18e3c91d (patch)
treecd4620b0d41dfe3f20164e570ed64faa8fa663ac /src/qml
parentfa53d4e35433cc59e99b24f16f18c713683c1a80 (diff)
Add a checksum to the generated QML compilation units
Change-Id: Icd5b1d805059981cbbb4c0eb2a5c842d59223839 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp16
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h2
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp13
-rw-r--r--src/qml/compiler/qv4compileddata_p.h10
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp3
-rw-r--r--src/qml/qml/qqmltypeloader_p.h4
8 files changed, 45 insertions, 6 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index f736e04b88..31250d0d57 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1359,7 +1359,7 @@ bool IRBuilder::isRedundantNullInitializerForPropertyDeclaration(Property *prope
return QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr);
}
-QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
+QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, QQmlEngine *engine, const QV4::CompiledData::ResolvedTypeReferenceMap &dependentTypes)
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit;
QV4::CompiledData::Unit *jsUnit = compilationUnit->createUnitData(&output);
@@ -1402,6 +1402,20 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
qmlUnit->offsetToStringTable = totalSize - output.jsGenerator.stringTable.sizeOfTableAndData();
qmlUnit->stringTableSize = output.jsGenerator.stringTable.stringCount();
+#ifndef V4_BOOTSTRAP
+ if (!dependentTypes.isEmpty()) {
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ if (dependentTypes.addToHash(&hash, engine)) {
+ QByteArray checksum = hash.result();
+ Q_ASSERT(checksum.size() == sizeof(qmlUnit->dependencyMD5Checksum));
+ memcpy(qmlUnit->dependencyMD5Checksum, checksum.constData(), sizeof(qmlUnit->dependencyMD5Checksum));
+ }
+ }
+#else
+ Q_UNUSED(dependentTypes);
+ Q_UNUSED(engine);
+#endif
+
// write imports
char *importPtr = data + qmlUnit->offsetToImports;
foreach (const QV4::CompiledData::Import *imp, output.imports) {
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 821a6bba6d..eedc262e7a 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -549,7 +549,7 @@ public:
struct Q_QML_PRIVATE_EXPORT QmlUnitGenerator
{
- QV4::CompiledData::Unit *generate(Document &output);
+ QV4::CompiledData::Unit *generate(Document &output, QQmlEngine *engine, const QV4::CompiledData::ResolvedTypeReferenceMap &dependentTypes);
private:
typedef bool (Binding::*BindingFilter)() const;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index a0b219e28e..68de9aee44 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -156,7 +156,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
// Generate QML compiled type data structures
QmlIR::QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document);
+ QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document, QQmlEnginePrivate::get(engine), resolvedTypes);
Q_ASSERT(document->javaScriptCompilationUnit);
// The js unit owns the data and will free the qml unit.
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 2aab1743cc..83ae9c56df 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -579,6 +579,19 @@ void ResolvedTypeReference::doDynamicTypeCheck()
mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
+
+bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
+{
+ for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
+ QQmlPropertyCache *pc = it.value()->createPropertyCache(engine);
+ bool ok = false;
+ hash->addData(pc->checksum(&ok));
+ if (!ok)
+ return false;
+ }
+ return true;
+}
+
#endif
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 82e303f27d..519708f089 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -611,6 +611,7 @@ struct Unit
LEUInt32 architectureIndex; // string index to QSysInfo::buildAbi()
LEUInt32 codeGeneratorIndex;
+ char dependencyMD5Checksum[16];
enum : unsigned int {
IsJavascript = 0x1,
@@ -788,7 +789,14 @@ struct ResolvedTypeReference
void doDynamicTypeCheck();
};
// map from name index
-typedef QHash<int, ResolvedTypeReference*> ResolvedTypeReferenceMap;
+// While this could be a hash, a map is chosen here to provide a stable
+// order, which is used to calculating a check-sum on dependent meta-objects.
+struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
+{
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
+};
+#else
+struct ResolvedTypeReferenceMap {};
#endif
// index is per-object binding index
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 768a4ffcd3..8503317430 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -361,6 +361,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
unit.qtVersion = QT_VERSION;
unit.architectureIndex = registerString(QSysInfo::buildAbi());
unit.codeGeneratorIndex = registerString(codeGeneratorName);
+ memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum));
quint32 nextOffset = sizeof(CompiledData::Unit);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index c54af43a6f..9f94aa41ec 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2910,7 +2910,8 @@ void QQmlScriptBlob::dataReceived(const Data &data)
irUnit.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
QmlIR::QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit);
+ QV4::CompiledData::ResolvedTypeReferenceMap emptyDependencies;
+ QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit, m_typeLoader->engine(), emptyDependencies);
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 ab6b046fcf..5f754df1fc 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -463,7 +463,9 @@ private:
QList<TypeReference> m_compositeSingletons;
// map from name index to resolved type
- QHash<int, TypeReference> m_resolvedTypes;
+ // While this could be a hash, a map is chosen here to provide a stable
+ // order, which is used to calculating a check-sum on dependent meta-objects.
+ QMap<int, TypeReference> m_resolvedTypes;
bool m_typesResolved:1;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compiledData;