diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2016-07-07 15:38:01 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-08-04 14:32:39 +0000 |
commit | 234e762265f0b538e65d610751b8488cb596824d (patch) | |
tree | a89a34a09de8ccc8ec87599257a11ec98da0a841 | |
parent | 01575a22ea2d2e54ef1748733929243ca024234b (diff) |
Use on-disk compilation unit if available
If we succeeded in saving the compilation unit to disk, then attempt to use it
right away. This replaces the C++ heap usage for the compilation unit data as
well as the anonymous allocated executable memory with file-backed mmap'ed
memory. That means the memory can be discarded when overall availability is low
and paged in on-demand.
Change-Id: Ide1b1e11752d861eb049a99a26ca12cec5e2502e
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 5 | ||||
-rw-r--r-- | src/qml/jit/qv4assembler.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 9 |
6 files changed, 25 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index cb5c14ebc2..98eb7188cc 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -424,6 +424,7 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory return false; } + const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; QScopedValueRollback<const Unit *> dataPtrChange(data, reinterpret_cast<const Unit *>(cacheData)); { @@ -448,6 +449,7 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory return false; dataPtrChange.commit(); + free(const_cast<Unit*>(oldDataPtr)); backingFile.reset(cacheFile.take()); return true; } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index d6537bbab3..639c79f79b 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -666,8 +666,10 @@ struct Unit return QString(); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN const QChar *characters = reinterpret_cast<const QChar *>(str + 1); - if (flags & StaticData) - return QString::fromRawData(characters, str->size); + // Too risky to do this while we unmap disk backed compilation but keep pointers to string + // data in the identifier tables. + // if (flags & StaticData) + // return QString::fromRawData(characters, str->size); return QString(characters, str->size); #else const LEUInt16 *characters = reinterpret_cast<const LEUInt16 *>(str + 1); diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 41790c04a9..c9143b6857 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1665,8 +1665,7 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit bool CompilationUnit::memoryMapCode(QString *errorString) { Q_UNUSED(errorString); - Q_ASSERT(codeRefs.isEmpty()); - codeRefs.reserve(data->functionTableSize); + codeRefs.resize(data->functionTableSize); const char *basePtr = reinterpret_cast<const char *>(data); @@ -1680,7 +1679,7 @@ bool CompilationUnit::memoryMapCode(QString *errorString) #else QByteArray code = QByteArray::fromRawData(codePtr, compiledFunction->codeSize); #endif - codeRefs.append(code); + codeRefs[i] = code; } return true; diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 625f5b5e5a..9c839936c2 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -129,8 +129,7 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit bool CompilationUnit::memoryMapCode(QString *errorString) { Q_UNUSED(errorString); - Q_ASSERT(codeRefs.isEmpty()); - codeRefs.reserve(data->functionTableSize); + codeRefs.resize(data->functionTableSize); const char *basePtr = reinterpret_cast<const char *>(data); @@ -139,7 +138,7 @@ bool CompilationUnit::memoryMapCode(QString *errorString) void *codePtr = const_cast<void *>(reinterpret_cast<const void *>(basePtr + compiledFunction->codeOffset)); JSC::MacroAssemblerCodeRef codeRef = JSC::MacroAssemblerCodeRef::createSelfManagedCodeRef(JSC::MacroAssemblerCodePtr(codePtr)); JSC::ExecutableAllocator::makeExecutable(codePtr, compiledFunction->codeSize); - codeRefs.append(codeRef); + codeRefs[i] = codeRef; } return true; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0e1f9572e0..a6cac8d8b5 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2502,7 +2502,8 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &importCache, { Q_ASSERT(m_compiledData.isNull()); - QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), this, m_document.data(), importCache, resolvedTypeCache); + QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine()); + QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), importCache, resolvedTypeCache); m_compiledData = compiler.compile(); if (!m_compiledData) { setError(compiler.compilationErrors()); @@ -2510,7 +2511,12 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &importCache, } if (diskCache() || forceDiskCacheRefresh()) { QString errorString; - if (!m_compiledData->saveToDisk(url(), &errorString)) { + if (m_compiledData->saveToDisk(url(), &errorString)) { + QString error; + if (!m_compiledData->loadFromDisk(url(), enginePrivate->v4engine()->iselFactory.data(), &error)) { + // ignore error, keep using the in-memory compilation unit. + } + } else { qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->url().toString() << "to disk:" << errorString; } } diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 1a035be5e0..f32051a26a 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -2118,8 +2118,13 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode() QQmlTypeData *td = eng->typeLoader.getType(url); Q_ASSERT(td); - const QV4::CompiledData::Unit *qmlUnit = td->compilationUnit()->data; - Q_ASSERT(qmlUnit); + const QV4::CompiledData::Unit *readOnlyQmlUnit = td->compilationUnit()->data; + Q_ASSERT(readOnlyQmlUnit); + QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(malloc(readOnlyQmlUnit->unitSize)); + memcpy(qmlUnit, readOnlyQmlUnit, readOnlyQmlUnit->unitSize); + qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData; + td->compilationUnit()->data = qmlUnit; + const QV4::CompiledData::Object *rootObject = qmlUnit->objectAt(qmlUnit->indexOfRootObject); QCOMPARE(qmlUnit->stringAt(rootObject->inheritedTypeNameIndex), QString("MyTypeObject")); quint32 i; |