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>
This commit is contained in:
parent
01575a22ea
commit
234e762265
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue