From 161473721dcdfd45e6618457a2c0a6e6b10bfada Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 22 Oct 2016 04:08:27 +0200 Subject: Add the ability to explicitly enable the code cache in qmljs This also requires mapping the label pointers in the byte code back to the instruction enum. Fortunately this reverse mapping is only needed in the qmljs case. Normally in the QML engine we persist the byte-code to disk before linking the compilation unit to the engine (where we map the enum to goto labels). Change-Id: If0b79288274bb1031161841b63a85f164502aaec Reviewed-by: Lars Knoll --- tools/qmljs/qmljs.cpp | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) (limited to 'tools/qmljs/qmljs.cpp') diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp index b4ffc9be16..4b63357363 100644 --- a/tools/qmljs/qmljs.cpp +++ b/tools/qmljs/qmljs.cpp @@ -51,6 +51,8 @@ QT_REQUIRE_CONFIG(qml_interpreter); #include #include +#include +#include #include #include #include @@ -147,6 +149,7 @@ int main(int argc, char *argv[]) #endif bool runAsQml = false; + bool cache = false; if (!args.isEmpty()) { if (args.first() == QLatin1String("--jit")) { @@ -166,6 +169,11 @@ int main(int argc, char *argv[]) args.removeFirst(); } + if (args.first() == QLatin1String("--cache")) { + cache = true; + args.removeFirst(); + } + if (args.first() == QLatin1String("--help")) { std::cerr << "Usage: qmljs [|--jit|--interpret|--qml] file..." << std::endl; return EXIT_SUCCESS; @@ -199,15 +207,38 @@ int main(int argc, char *argv[]) for (const QString &fn : qAsConst(args)) { QFile file(fn); if (file.open(QFile::ReadOnly)) { - const QString code = QString::fromUtf8(file.readAll()); - file.close(); + QScopedPointer script; + if (cache && QFile::exists(fn + QLatin1Char('c'))) { + QQmlRefPointer unit = iSelFactory->createUnitForLoading(); + QString error; + if (unit->loadFromDisk(QUrl::fromLocalFile(fn), iSelFactory, &error)) { + script.reset(new QV4::Script(&vm, nullptr, unit)); + } else { + std::cout << "Error loading" << qPrintable(fn) << "from disk cache:" << qPrintable(error) << std::endl; + } + } + if (!script) { + const QString code = QString::fromUtf8(file.readAll()); + file.close(); + script.reset(new QV4::Script(ctx, code, fn)); + script->parseAsBinding = runAsQml; + script->parse(); + } QV4::ScopedValue result(scope); - QV4::Script script(ctx, code, fn); - script.parseAsBinding = runAsQml; - script.parse(); - if (!scope.engine->hasException) - result = script.run(); + if (!scope.engine->hasException) { + const auto unit = script->compilationUnit; + if (cache && unit && !(unit->data->flags & QV4::CompiledData::Unit::StaticData)) { + if (unit->data->sourceTimeStamp == 0) { + const_cast(unit->data)->sourceTimeStamp = QFileInfo(fn).lastModified().toMSecsSinceEpoch(); + } + QString saveError; + if (!unit->saveToDisk(QUrl::fromLocalFile(fn), &saveError)) { + std::cout << "Error saving JS cache file: " << qPrintable(saveError) << std::endl; + } + } + result = script->run(); + } if (scope.engine->hasException) { QV4::StackTrace trace; QV4::ScopedValue ex(scope, scope.engine->catchException(&trace)); -- cgit v1.2.3