aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2018-07-20 09:22:47 -0700
committerSimon Hausmann <simon.hausmann@qt.io>2018-07-27 04:56:14 +0000
commit447e2e024609a22fe052cf458c27efdef2e3d3eb (patch)
treef2665cfdea84b9d85044a3221658eb8ce10e7d9a /src
parent65fd9165162a8498c5bbe71e5372b65770c240b0 (diff)
Try to load QML cache from CacheLocation if side-by-side fails
This could happen if the .qmlc file is stale or corrupt for some reason. In that case, we should try to load a cache file from the user's CacheLocation. Change-Id: Id2be776c7ae0467c9d9ffffd1543204272a531d1 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4compileddata.cpp44
-rw-r--r--src/qml/compiler/qv4compileddata_p.h4
-rw-r--r--src/qml/compiler/qv4compiler.cpp5
3 files changed, 32 insertions, 21 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 02aee47eea..0c81a5b3c6 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -76,7 +76,18 @@ namespace QV4 {
namespace CompiledData {
+#if defined(QML_COMPILE_HASH)
+# ifdef Q_OS_LINUX
+// Place on a separate section on Linux so it's easier to check from outside
+// what the hash version is.
+__attribute__((section(".qml_compile_hash")))
+# endif
+const char qml_compile_hash[48 + 1] = QML_COMPILE_HASH;
static_assert(sizeof(Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1, "Compile hash length exceeds reserved size in data structure. Please adjust and bump the format version");
+#else
+# error "QML_COMPILE_HASH must be defined for the build of QtDeclarative to ensure version checking for cache files"
+#endif
+
CompilationUnit::CompilationUnit(const Unit *unitData)
{
@@ -351,26 +362,27 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeS
const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
- QString cachePath = sourcePath + QLatin1Char('c');
- if (!QFile::exists(cachePath))
- cachePath = localCacheFilePath(url);
+ const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) };
+ for (const QString &cachePath : cachePaths) {
+ CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
+ if (!mappedUnit)
+ continue;
- CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
- if (!mappedUnit)
- return false;
+ const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
+ QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
- const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
- QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
+ if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
+ *errorString = QStringLiteral("QML source file has moved to a different location.");
+ continue;
+ }
- if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
- *errorString = QStringLiteral("QML source file has moved to a different location.");
- return false;
+ dataPtrChange.commit();
+ free(const_cast<Unit*>(oldDataPtr));
+ backingFile.reset(cacheFile.take());
+ return true;
}
- dataPtrChange.commit();
- free(const_cast<Unit*>(oldDataPtr));
- backingFile.reset(cacheFile.take());
- return true;
+ return false;
}
void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
@@ -783,7 +795,7 @@ bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString)
}
#if defined(QML_COMPILE_HASH)
- if (qstrcmp(QML_COMPILE_HASH, libraryVersionHash) != 0) {
+ if (qstrcmp(CompiledData::qml_compile_hash, libraryVersionHash) != 0) {
*errorString = QStringLiteral("QML library version mismatch. Expected compile hash does not match");
return false;
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index c1be00ea27..0ac40d2800 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -752,7 +752,9 @@ struct Import
};
static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+enum { QmlCompileHashSpace = 48 };
static const char magic_str[] = "qv4cdata";
+extern const char qml_compile_hash[QmlCompileHashSpace + 1];
struct Unit
{
@@ -764,7 +766,7 @@ struct Unit
quint32_le unitSize; // Size of the Unit and any depending data.
// END DO NOT CHANGE THESE FIELDS EVER
- char libraryVersionHash[48];
+ char libraryVersionHash[QmlCompileHashSpace];
char md5Checksum[16]; // checksum of all bytes following this field.
void generateChecksum();
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index f1afad4965..76779fece8 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -48,9 +48,6 @@
#include <wtf/MathExtras.h>
#include <QCryptographicHash>
-// generated by qmake:
-#include "qml_compile_hash_p.h"
-
QV4::Compiler::StringTableGenerator::StringTableGenerator()
{
clear();
@@ -482,7 +479,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
unit.flags |= module->unitFlags;
unit.version = QV4_DATA_STRUCTURE_VERSION;
unit.qtVersion = QT_VERSION;
- qstrcpy(unit.libraryVersionHash, QML_COMPILE_HASH);
+ qstrcpy(unit.libraryVersionHash, CompiledData::qml_compile_hash);
memset(unit.md5Checksum, 0, sizeof(unit.md5Checksum));
memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum));