Avoid an extra stat() on the source .qml file when loading cache

For timestamp comparison it is not necessary to create another
QFileInfo() object and call exists() and lastModified(), when we can
pass that information through from the type loader.

Change-Id: I225cd36e672f1f390bddb4e6ebfafa3fc1269795
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Simon Hausmann 2017-03-16 09:44:50 +01:00
parent 9b70716374
commit 5bd11b5a8c
12 changed files with 26 additions and 30 deletions

View File

@ -59,7 +59,7 @@ CompilationUnitMapper::~CompilationUnitMapper()
close();
}
bool CompilationUnitMapper::verifyHeader(const CompiledData::Unit *header, const QString &sourcePath, QString *errorString)
bool CompilationUnitMapper::verifyHeader(const CompiledData::Unit *header, QDateTime sourceTimeStamp, QString *errorString)
{
if (strncmp(header->magic, CompiledData::magic_str, sizeof(header->magic))) {
*errorString = QStringLiteral("Magic bytes in the header do not match");
@ -77,11 +77,6 @@ bool CompilationUnitMapper::verifyHeader(const CompiledData::Unit *header, const
}
if (header->sourceTimeStamp) {
QFileInfo sourceCode(sourcePath);
QDateTime sourceTimeStamp;
if (sourceCode.exists())
sourceTimeStamp = sourceCode.lastModified();
// Files from the resource system do not have any time stamps, so fall back to the application
// executable.
if (!sourceTimeStamp.isValid())

View File

@ -68,11 +68,11 @@ public:
CompilationUnitMapper();
~CompilationUnitMapper();
CompiledData::Unit *open(const QString &cacheFilePath, const QString &sourcePath, QString *errorString);
CompiledData::Unit *open(const QString &cacheFilePath, const QDateTime &sourceTimeStamp, QString *errorString);
void close();
private:
static bool verifyHeader(const QV4::CompiledData::Unit *header, const QString &sourcePath, QString *errorString);
static bool verifyHeader(const QV4::CompiledData::Unit *header, QDateTime sourceTimeStamp, QString *errorString);
#if defined(Q_OS_UNIX)
size_t length;

View File

@ -43,6 +43,7 @@
#include <functional>
#include <private/qcore_unix_p.h>
#include <private/qdeferredcleanup_p.h>
#include <QDateTime>
#include "qv4compileddata_p.h"
@ -50,7 +51,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QString &sourcePath, QString *errorString)
CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QDateTime &sourceTimeStamp, QString *errorString)
{
close();
@ -72,7 +73,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
return nullptr;
}
if (!verifyHeader(&header, sourcePath, errorString))
if (!verifyHeader(&header, sourceTimeStamp, errorString))
return nullptr;
// Data structure and qt version matched, so now we can access the rest of the file safely.

View File

@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QString &sourcePath, QString *errorString)
CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QDateTime &sourceTimeStamp, QString *errorString)
{
close();
@ -87,7 +87,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
return nullptr;
}
if (!verifyHeader(&header, sourcePath, errorString))
if (!verifyHeader(&header, sourceTimeStamp, errorString))
return nullptr;
const uint mappingFlags = header.flags & QV4::CompiledData::Unit::ContainsMachineCode

View File

@ -343,7 +343,7 @@ bool CompilationUnit::verifyChecksum(QQmlEngine *engine,
sizeof(data->dependencyMD5Checksum)) == 0;
}
bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString)
bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, EvalISelFactory *iselFactory, QString *errorString)
{
if (!QQmlFile::isLocalFile(url)) {
*errorString = QStringLiteral("File has to be a local file.");
@ -353,7 +353,7 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory
const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
CompiledData::Unit *mappedUnit = cacheFile->open(cacheFilePath(url), sourcePath, errorString);
CompiledData::Unit *mappedUnit = cacheFile->open(cacheFilePath(url), sourceTimeStamp, errorString);
if (!mappedUnit)
return false;

View File

@ -899,7 +899,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public
void destroy() Q_DECL_OVERRIDE;
bool loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString);
bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, EvalISelFactory *iselFactory, QString *errorString);
protected:
virtual void linkBackendToEngine(QV4::ExecutionEngine *engine) = 0;

View File

@ -425,7 +425,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
}
unit.indexOfRootFunction = -1;
unit.sourceFileIndex = getStringId(irModule->fileName);
unit.sourceTimeStamp = irModule->sourceTimeStamp;
unit.sourceTimeStamp = irModule->sourceTimeStamp.isValid() ? irModule->sourceTimeStamp.toMSecsSinceEpoch() : 0;
unit.nImports = 0;
unit.offsetToImports = 0;
unit.nObjects = 0;

View File

@ -61,6 +61,7 @@
#include <QtCore/QBitArray>
#include <QtCore/qurl.h>
#include <QtCore/QVarLengthArray>
#include <QtCore/QDateTime>
#include <qglobal.h>
#if defined(CONST) && defined(Q_OS_WIN)
@ -942,7 +943,7 @@ struct Q_QML_PRIVATE_EXPORT Module {
QVector<Function *> functions;
Function *rootFunction;
QString fileName;
qint64 sourceTimeStamp;
QDateTime sourceTimeStamp;
bool isQmlModule; // implies rootFunction is always 0
uint unitFlags; // flags merged into CompiledData::Unit::flags
#ifdef QT_NO_QML_DEBUGGER
@ -955,7 +956,6 @@ struct Q_QML_PRIVATE_EXPORT Module {
Module(bool debugMode)
: rootFunction(0)
, sourceTimeStamp(0)
, isQmlModule(false)
, unitFlags(0)
#ifndef QT_NO_QML_DEBUGGER

View File

@ -2065,7 +2065,7 @@ bool QQmlTypeData::tryLoadFromDiskCache()
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
{
QString error;
if (!unit->loadFromDisk(url(), v4->iselFactory.data(), &error)) {
if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), v4->iselFactory.data(), &error)) {
qCDebug(DBG_DISK_CACHE) << "Error loading" << url().toString() << "from disk cache:" << error;
return false;
}
@ -2522,7 +2522,7 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach
QString errorString;
if (m_compiledData->saveToDisk(url(), &errorString)) {
QString error;
if (!m_compiledData->loadFromDisk(url(), enginePrivate->v4engine()->iselFactory.data(), &error)) {
if (!m_compiledData->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), enginePrivate->v4engine()->iselFactory.data(), &error)) {
// ignore error, keep using the in-memory compilation unit.
}
} else {
@ -2882,7 +2882,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
if (!disableDiskCache() || forceDiskCache()) {
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
QString error;
if (unit->loadFromDisk(url(), v4->iselFactory.data(), &error)) {
if (unit->loadFromDisk(url(), data.sourceTimeStamp(), v4->iselFactory.data(), &error)) {
initializeFromCompilationUnit(unit);
return;
} else {
@ -3094,18 +3094,18 @@ QString QQmlDataBlob::SourceCodeData::readAll(QString *error) const
return QString::fromUtf8(data);
}
qint64 QQmlDataBlob::SourceCodeData::sourceTimeStamp() const
QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp() const
{
if (!inlineSourceCode.isEmpty())
return 0;
return QDateTime();
QDateTime timeStamp = fileInfo.lastModified();
if (timeStamp.isValid())
return timeStamp.toMSecsSinceEpoch();
return timeStamp;
static qint64 appTimeStamp = 0;
if (appTimeStamp == 0)
appTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified().toMSecsSinceEpoch();
static QDateTime appTimeStamp;
if (!appTimeStamp.isValid())
appTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
return appTimeStamp;
}

View File

@ -134,7 +134,7 @@ public:
class SourceCodeData {
public:
QString readAll(QString *error) const;
qint64 sourceTimeStamp() const;
QDateTime sourceTimeStamp() const;
bool exists() const;
private:
friend class QQmlDataBlob;

View File

@ -174,7 +174,7 @@ struct TestCompiler
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), v4->iselFactory.data(), &lastErrorString);
return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), QFileInfo(testFilePath).lastModified(), v4->iselFactory.data(), &lastErrorString);
}
void closeMapping()

View File

@ -159,7 +159,7 @@ int main(int argc, char *argv[])
if (cache && QFile::exists(fn + QLatin1Char('c'))) {
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = iSelFactory->createUnitForLoading();
QString error;
if (unit->loadFromDisk(QUrl::fromLocalFile(fn), iSelFactory, &error)) {
if (unit->loadFromDisk(QUrl::fromLocalFile(fn), QFileInfo(fn).lastModified(), iSelFactory, &error)) {
script.reset(new QV4::Script(&vm, nullptr, unit));
} else {
std::cout << "Error loading" << qPrintable(fn) << "from disk cache:" << qPrintable(error) << std::endl;