From cfdc612c3022b3f35545fd5e4e0bcd2661f657f1 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Dec 2023 13:25:11 +0100 Subject: QtQml: Make base CU a member of ExecutableCompilationUnit We want to re-use the base compilation unit across engines. For that to work it cannot be a slice of the engine-specific ExecutableCompilationUnit. Since CompiledData::CompilationUnit is refcounted on its own now, make it unmovable. Change-Id: I8418c9754d7a07e5210c1e7a7fc69355e1d57807 Reviewed-by: Fabian Kosmale --- src/qml/common/qv4compileddata_p.h | 32 ++-------- src/qml/compiler/qqmlirbuilder.cpp | 16 +++-- src/qml/compiler/qqmlirbuilder_p.h | 2 +- src/qml/compiler/qv4codegen.cpp | 14 +++-- src/qml/compiler/qv4codegen_p.h | 5 +- src/qml/debugger/qqmldebugserviceinterfaces.cpp | 4 +- src/qml/jsruntime/qv4engine.cpp | 8 ++- src/qml/jsruntime/qv4executablecompilationunit.cpp | 58 ++++++++++++------ src/qml/jsruntime/qv4executablecompilationunit_p.h | 70 +++++++++++++++------- src/qml/jsruntime/qv4module.cpp | 6 +- src/qml/jsruntime/qv4resolvedtypereference.cpp | 4 +- src/qml/jsruntime/qv4script.cpp | 7 ++- src/qml/jsruntime/qv4script_p.h | 2 +- src/qml/qml/qqmlbuiltinfunctions.cpp | 2 +- src/qml/qml/qqmlscriptblob.cpp | 8 ++- src/qml/qml/qqmltypecompiler.cpp | 4 +- src/qml/qml/qqmltypedata.cpp | 20 ++++--- src/qml/qml/qqmltypedata_p.h | 2 +- src/qmlcompiler/qqmljscompiler.cpp | 11 ++-- tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 2 +- tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp | 2 +- tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp | 6 +- tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 2 +- .../qml/qqmltranslation/tst_qqmltranslation.cpp | 8 +-- tests/auto/toolsupport/tst_toolsupport.cpp | 2 +- 25 files changed, 170 insertions(+), 127 deletions(-) diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index f033a43aaa..82424c1c9d 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -30,7 +30,9 @@ #endif #include +#include #include + #include #include @@ -1421,9 +1423,9 @@ using DependentTypesHasher = std::function; // This is how this hooks into the existing structures: -struct CompilationUnit +struct CompilationUnit final : public QQmlRefCounted { - Q_DISABLE_COPY(CompilationUnit) + Q_DISABLE_COPY_MOVE(CompilationUnit) const Unit *data = nullptr; const QmlUnit *qmlData = nullptr; @@ -1465,32 +1467,6 @@ public: #endif } - CompilationUnit(CompilationUnit &&other) noexcept - { - *this = std::move(other); - } - - CompilationUnit &operator=(CompilationUnit &&other) noexcept - { - if (this != &other) { - data = other.data; - other.data = nullptr; - qmlData = other.qmlData; - other.qmlData = nullptr; - dynamicStrings = std::move(other.dynamicStrings); - other.dynamicStrings.clear(); - aotCompiledFunctions = other.aotCompiledFunctions; - other.aotCompiledFunctions = nullptr; - constants = other.constants; - other.constants = nullptr; - m_fileName = std::move(other.m_fileName); - other.m_fileName.clear(); - m_finalUrlString = std::move(other.m_finalUrlString); - other.m_finalUrlString.clear(); - } - return *this; - } - const Unit *unitData() const { return data; } void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr, diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 96529f0061..a81f8fb1d8 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1645,10 +1645,14 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen Unit *jsUnit = nullptr; + if (!output.javaScriptCompilationUnit) + output.javaScriptCompilationUnit.adopt(new QV4::CompiledData::CompilationUnit); + // We may already have unit data if we're loading an ahead-of-time generated cache file. - if (output.javaScriptCompilationUnit.data) { - jsUnit = const_cast(output.javaScriptCompilationUnit.data); - output.javaScriptCompilationUnit.dynamicStrings = output.jsGenerator.stringTable.allStrings(); + if (output.javaScriptCompilationUnit->unitData()) { + jsUnit = const_cast(output.javaScriptCompilationUnit->unitData()); + output.javaScriptCompilationUnit->dynamicStrings + = output.jsGenerator.stringTable.allStrings(); } else { Unit *createdUnit; jsUnit = createdUnit = output.jsGenerator.generateUnit(); @@ -1921,7 +1925,7 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen } } - if (!output.javaScriptCompilationUnit.data) { + if (!output.javaScriptCompilationUnit->unitData()) { // Combine the qml data into the general unit data. jsUnit = static_cast(realloc(jsUnit, jsUnit->unitSize + totalSize)); jsUnit->offsetToQmlUnit = jsUnit->unitSize; @@ -1954,8 +1958,8 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen qDebug() << " " << totalStringSize << "bytes total strings"; } - output.javaScriptCompilationUnit.setUnitData(jsUnit, qmlUnit, output.jsModule.fileName, - output.jsModule.finalUrl); + output.javaScriptCompilationUnit->setUnitData( + jsUnit, qmlUnit, output.jsModule.fileName, output.jsModule.finalUrl); } char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index eace7b2549..546d1fac58 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -472,7 +472,7 @@ struct Q_QML_COMPILER_EXPORT Document QVector objects; QV4::Compiler::JSUnitGenerator jsGenerator; - QV4::CompiledData::CompilationUnit javaScriptCompilationUnit; + QQmlRefPointer javaScriptCompilationUnit; bool isSingleton() const { return std::any_of(pragmas.constBegin(), pragmas.constEnd(), [](const Pragma *pragma) { diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 580406db86..7c312d9a3e 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -4129,14 +4129,16 @@ QQmlJS::DiagnosticMessage Codegen::error() const return _error; } -QV4::CompiledData::CompilationUnit Codegen::generateCompilationUnit( +QQmlRefPointer Codegen::generateCompilationUnit( bool generateUnitData) { - return QV4::CompiledData::CompilationUnit( - generateUnitData ? jsUnitGenerator->generateUnit() : nullptr); + return QQmlRefPointer( + new QV4::CompiledData::CompilationUnit( + generateUnitData ? jsUnitGenerator->generateUnit() : nullptr), + QQmlRefPointer::Adopt); } -CompiledData::CompilationUnit Codegen::compileModule( +QQmlRefPointer Codegen::compileModule( bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList *diagnostics) { @@ -4151,7 +4153,7 @@ CompiledData::CompilationUnit Codegen::compileModule( *diagnostics = parser.diagnosticMessages(); if (!parsed) - return CompiledData::CompilationUnit(); + return QQmlRefPointer(); QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast(parser.rootNode()); if (!moduleNode) { @@ -4172,7 +4174,7 @@ CompiledData::CompilationUnit Codegen::compileModule( if (cg.hasError()) { if (diagnostics) *diagnostics << cg.error(); - return CompiledData::CompilationUnit(); + return QQmlRefPointer(); } return cg.generateCompilationUnit(); diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index eb4acea437..d9a04dcd92 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -731,8 +731,9 @@ public: const QString &name, bool lhs, const QQmlJS::SourceLocation &accessLocation = QQmlJS::SourceLocation()); - QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true); - static QV4::CompiledData::CompilationUnit compileModule( + QQmlRefPointer generateCompilationUnit( + bool generateUnitData = true); + static QQmlRefPointer compileModule( bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList *diagnostics); diff --git a/src/qml/debugger/qqmldebugserviceinterfaces.cpp b/src/qml/debugger/qqmldebugserviceinterfaces.cpp index 1dc0a3556f..db1ec2db5e 100644 --- a/src/qml/debugger/qqmldebugserviceinterfaces.cpp +++ b/src/qml/debugger/qqmldebugserviceinterfaces.cpp @@ -54,7 +54,7 @@ const TranslationBindingInformation TranslationBindingInformation::create( QQmlTranslation translation; if (binding->type() == QV4::CompiledData::Binding::Type_TranslationById) { const QV4::CompiledData::TranslationData data = - compilationUnit->data->translations()[binding->value.translationDataIndex]; + compilationUnit->unitData()->translations()[binding->value.translationDataIndex]; const QString id = compilationUnit->stringAt(data.stringIndex); const int n = data.number; @@ -63,7 +63,7 @@ const TranslationBindingInformation TranslationBindingInformation::create( Q_ASSERT(binding->type() == QV4::CompiledData::Binding::Type_Translation); const QV4::CompiledData::TranslationData data = - compilationUnit->data->translations()[binding->value.translationDataIndex]; + compilationUnit->unitData()->translations()[binding->value.translationDataIndex]; const QString text = compilationUnit->stringAt(data.stringIndex); const QString comment = compilationUnit->stringAt(data.commentIndex); const bool hasContext diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 2d128e05dc..344f57b638 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -2075,9 +2075,11 @@ QQmlRefPointer ExecutionEngine::compileModule(const Q &cacheError) : nullptr) { return ExecutableCompilationUnit::create( - QV4::CompiledData::CompilationUnit( - cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, - url.fileName(), url.toString())); + QQmlRefPointer( + new QV4::CompiledData::CompilationUnit( + cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, + url.fileName(), url.toString()), + QQmlRefPointer::Adopt)); } QFile f(QQmlFile::urlToLocalFileOrQrc(url)); diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index 2ab38b70d9..a622c14362 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -55,10 +55,10 @@ namespace QV4 { ExecutableCompilationUnit::ExecutableCompilationUnit() = default; ExecutableCompilationUnit::ExecutableCompilationUnit( - CompiledData::CompilationUnit &&compilationUnit) - : CompiledData::CompilationUnit(std::move(compilationUnit)) + QQmlRefPointer &&compilationUnit) + : m_compilationUnit(std::move(compilationUnit)) { - CompilationUnitRuntimeData::constants = CompiledData::CompilationUnit::constants; + constants = m_compilationUnit->constants; } ExecutableCompilationUnit::~ExecutableCompilationUnit() @@ -112,6 +112,8 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine) this->engine = engine; engine->compilationUnits.insert(this); + const CompiledData::Unit *data = m_compilationUnit->data; + Q_ASSERT(!runtimeStrings); Q_ASSERT(data); const quint32 stringCount = totalStringCount(); @@ -182,7 +184,7 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine) || !(engine->diskCacheOptions() & ExecutionEngine::DiskCache::AotNative); const QQmlPrivate::AOTCompiledFunction *aotFunction - = ignoreAotCompiledFunctions ? nullptr : aotCompiledFunctions; + = ignoreAotCompiledFunctions ? nullptr : m_compilationUnit->aotCompiledFunctions; auto advanceAotFunction = [&](int i) -> const QQmlPrivate::AOTCompiledFunction * { if (aotFunction) { @@ -222,7 +224,7 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine) static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); if (showCode) { qDebug() << "=== Constant table"; - dumpConstantTable(CompiledData::CompilationUnit::constants, data->constantTableSize); + dumpConstantTable(constants, data->constantTableSize); qDebug() << "=== String table"; for (uint i = 0, end = totalStringCount(); i < end; ++i) qDebug() << " " << i << ":" << runtimeStrings[i]->toQString(); @@ -242,6 +244,8 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine) Heap::Object *ExecutableCompilationUnit::templateObjectAt(int index) const { + const CompiledData::Unit *data = m_compilationUnit->data; + Q_ASSERT(index < int(data->templateObjectTableSize)); if (!templateObjects.size()) templateObjects.resize(data->templateObjectTableSize); @@ -282,7 +286,8 @@ void ExecutableCompilationUnit::unlink() ic.qmlType = QQmlType(); if (runtimeLookups) { - for (uint i = 0; i < data->lookupTableSize; ++i) + const uint lookupTableSize = unitData()->lookupTableSize; + for (uint i = 0; i < lookupTableSize; ++i) runtimeLookups[i].releasePropertyCache(); } @@ -312,6 +317,8 @@ void ExecutableCompilationUnit::unlink() void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack) { + const CompiledData::Unit *data = m_compilationUnit->data; + if (runtimeStrings) { for (uint i = 0, end = totalStringCount(); i < end; ++i) if (runtimeStrings[i]) @@ -521,6 +528,8 @@ int ExecutableCompilationUnit::totalParserStatusCount() const { bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const { + const CompiledData::Unit *data = m_compilationUnit->data; + if (!dependencyHasher) { for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) { if (data->dependencyMD5Checksum[i] != 0) @@ -543,6 +552,8 @@ QQmlType ExecutableCompilationUnit::qmlTypeForComponent(const QString &inlineCom QStringList ExecutableCompilationUnit::moduleRequests() const { + const CompiledData::Unit *data = m_compilationUnit->data; + QStringList requests; requests.reserve(data->moduleRequestTableSize); for (uint i = 0; i < data->moduleRequestTableSize; ++i) @@ -552,6 +563,8 @@ QStringList ExecutableCompilationUnit::moduleRequests() const Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine) { + const CompiledData::Unit *data = m_compilationUnit->data; + if (isESModule() && module()) return module(); @@ -687,6 +700,7 @@ const Value *ExecutableCompilationUnit::resolveExportRecursively( if (exportName->toQString() == QLatin1String("*")) return &module()->self; + const CompiledData::Unit *data = m_compilationUnit->data; Scope scope(engine); if (auto localExport = lookupNameInExportTable( @@ -797,6 +811,8 @@ void ExecutableCompilationUnit::getExportedNamesRecursively( names->append(name); }; + const CompiledData::Unit *data = m_compilationUnit->data; + for (uint i = 0; i < data->localExportEntryTableSize; ++i) { const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i]; append(stringAt(entry.exportName)); @@ -867,21 +883,25 @@ bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &s if (!mappedUnit) continue; + const CompiledData::Unit *oldData = unitData(); const CompiledData::Unit * const oldDataPtr - = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data - : nullptr; - const CompiledData::Unit *oldData = data; + = (oldData && !(oldData->flags & QV4::CompiledData::Unit::StaticData)) + ? oldData + : nullptr; + auto dataPtrRevert = qScopeGuard([this, oldData](){ - setUnitData(oldData); + m_compilationUnit->setUnitData(oldData); }); - setUnitData(mappedUnit); + m_compilationUnit->setUnitData(mappedUnit); - if (data->sourceFileIndex != 0) { - if (data->sourceFileIndex >= data->stringTableSize + dynamicStrings.size()) { + if (mappedUnit->sourceFileIndex != 0) { + if (mappedUnit->sourceFileIndex >= + mappedUnit->stringTableSize + m_compilationUnit->dynamicStrings.size()) { *errorString = QStringLiteral("QML source file index is invalid."); continue; } - if (sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) { + if (sourcePath != + QQmlFile::urlToLocalFileOrQrc(stringAt(mappedUnit->sourceFileIndex))) { *errorString = QStringLiteral("QML source file has moved to a different location."); continue; } @@ -890,7 +910,7 @@ bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &s dataPtrRevert.dismiss(); free(const_cast(oldDataPtr)); backingFile = std::move(cacheFile); - CompilationUnitRuntimeData::constants = CompiledData::CompilationUnit::constants; + CompilationUnitRuntimeData::constants = m_compilationUnit->constants; return true; } @@ -899,7 +919,7 @@ bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &s bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString) { - if (data->sourceTimeStamp == 0) { + if (unitData()->sourceTimeStamp == 0) { *errorString = QStringLiteral("Missing time stamp for source file"); return false; } @@ -961,7 +981,7 @@ QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Bind break; } #endif - return CompilationUnit::bindingValueAsString(binding); + return m_compilationUnit->bindingValueAsString(binding); } QString ExecutableCompilationUnit::translateFrom(TranslationDataIndex index) const @@ -969,7 +989,7 @@ QString ExecutableCompilationUnit::translateFrom(TranslationDataIndex index) con #if !QT_CONFIG(translation) return QString(); #else - const CompiledData::TranslationData &translation = data->translations()[index.index]; + const CompiledData::TranslationData &translation = unitData()->translations()[index.index]; if (index.byId) { QByteArray id = stringAt(translation.stringIndex).toUtf8(); @@ -993,7 +1013,7 @@ QString ExecutableCompilationUnit::translateFrom(TranslationDataIndex index) con if (hasContext) { context = stringAt(translation.contextIndex).toUtf8(); } else { - auto pragmaTranslationContext = data->translationContextIndex(); + auto pragmaTranslationContext = unitData()->translationContextIndex(); context = stringAt(*pragmaTranslationContext).toUtf8(); context = context.isEmpty() ? fileContext() : context; } diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 6b29760d35..f52989ec25 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -91,8 +91,7 @@ static_assert(offsetof(CompilationUnitRuntimeData, runtimeClasses) == offsetof(C static_assert(offsetof(CompilationUnitRuntimeData, imports) == offsetof(CompilationUnitRuntimeData, runtimeClasses) + sizeof(const StaticValue *)); class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final - : public CompiledData::CompilationUnit, - public CompilationUnitRuntimeData, + : public CompilationUnitRuntimeData, public QQmlRefCounted { Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit) @@ -101,7 +100,7 @@ public: friend class QQmlRefPointer; static QQmlRefPointer create( - CompiledData::CompilationUnit &&compilationUnit) + QQmlRefPointer &&compilationUnit) { return QQmlRefPointer( new ExecutableCompilationUnit(std::move(compilationUnit)), @@ -111,13 +110,19 @@ public: static QQmlRefPointer create() { return QQmlRefPointer( - new ExecutableCompilationUnit, + new ExecutableCompilationUnit( + QQmlRefPointer( + new CompiledData::CompilationUnit, + QQmlRefPointer::Adopt)), QQmlRefPointer::Adopt); } QIntrusiveListNode nextCompilationUnit; ExecutionEngine *engine = nullptr; + QString finalUrlString() const { return m_compilationUnit->finalUrlString(); } + QString fileName() const { return m_compilationUnit->fileName(); } + // url() and fileName() shall be used to load the actual QML/JS code or to show errors or // warnings about that code. They include any potential URL interceptions and thus represent the // "physical" location of the code. @@ -128,14 +133,14 @@ public: QUrl url() const { if (!m_url.isValid()) - m_url = QUrl(fileName()); + m_url = QUrl(m_compilationUnit->fileName()); return m_url; } QUrl finalUrl() const { if (!m_finalUrl.isValid()) - m_finalUrl = QUrl(finalUrlString()); + m_finalUrl = QUrl(m_compilationUnit->finalUrlString()); return m_finalUrl; } @@ -216,48 +221,48 @@ public: ListPropertyAssignBehavior listPropertyAssignBehavior() const { - if (data->flags & CompiledData::Unit::ListPropertyAssignReplace) + if (unitData()->flags & CompiledData::Unit::ListPropertyAssignReplace) return ListPropertyAssignBehavior::Replace; - if (data->flags & CompiledData::Unit::ListPropertyAssignReplaceIfNotDefault) + if (unitData()->flags & CompiledData::Unit::ListPropertyAssignReplaceIfNotDefault) return ListPropertyAssignBehavior::ReplaceIfNotDefault; return ListPropertyAssignBehavior::Append; } bool ignoresFunctionSignature() const { - return data->flags & CompiledData::Unit::FunctionSignaturesIgnored; + return unitData()->flags & CompiledData::Unit::FunctionSignaturesIgnored; } bool nativeMethodsAcceptThisObjects() const { - return data->flags & CompiledData::Unit::NativeMethodsAcceptThisObject; + return unitData()->flags & CompiledData::Unit::NativeMethodsAcceptThisObject; } bool valueTypesAreCopied() const { - return data->flags & CompiledData::Unit::ValueTypesCopied; + return unitData()->flags & CompiledData::Unit::ValueTypesCopied; } bool valueTypesAreAddressable() const { - return data->flags & CompiledData::Unit::ValueTypesAddressable; + return unitData()->flags & CompiledData::Unit::ValueTypesAddressable; } bool componentsAreBound() const { - return data->flags & CompiledData::Unit::ComponentsBound; + return unitData()->flags & CompiledData::Unit::ComponentsBound; } - int objectCount() const { return qmlData->nObjects; } + int objectCount() const { return qmlData()->nObjects; } const CompiledObject *objectAt(int index) const { - return qmlData->objectAt(index); + return qmlData()->objectAt(index); } - int importCount() const { return qmlData->nImports; } + int importCount() const { return qmlData()->nImports; } const CompiledData::Import *importAt(int index) const { - return qmlData->importAt(index); + return qmlData()->importAt(index); } Heap::Object *templateObjectAt(int index) const; @@ -282,22 +287,22 @@ public: FunctionIterator objectFunctionsBegin(const CompiledObject *object) const { - return FunctionIterator(data, object, 0); + return FunctionIterator(unitData(), object, 0); } FunctionIterator objectFunctionsEnd(const CompiledObject *object) const { - return FunctionIterator(data, object, object->nFunctions); + return FunctionIterator(unitData(), object, object->nFunctions); } bool isESModule() const { - return data->flags & CompiledData::Unit::IsESModule; + return unitData()->flags & CompiledData::Unit::IsESModule; } bool isSharedLibrary() const { - return data->flags & CompiledData::Unit::IsSharedLibrary; + return unitData()->flags & CompiledData::Unit::IsSharedLibrary; } QStringList moduleRequests() const; @@ -333,6 +338,14 @@ public: bool saveToDisk(const QUrl &unitUrl, QString *errorString); QString bindingValueAsString(const CompiledData::Binding *binding) const; + double bindingValueAsNumber(const CompiledData::Binding *binding) const + { + return m_compilationUnit->bindingValueAsNumber(binding); + } + QString bindingValueAsScriptString(const CompiledData::Binding *binding) const + { + return m_compilationUnit->bindingValueAsScriptString(binding); + } struct TranslationDataIndex { @@ -348,11 +361,22 @@ public: Heap::Module *module() const { return m_module; } void setModule(Heap::Module *module) { m_module = module; } + const CompiledData::Unit *unitData() const { return m_compilationUnit->data; } + const CompiledData::QmlUnit *qmlData() const { return m_compilationUnit->qmlData; } + + QString stringAt(uint index) const { return m_compilationUnit->stringAt(index); } + + QQmlRefPointer baseCompilationUnit() const + { + return m_compilationUnit; + } + protected: quint32 totalStringCount() const - { return data->stringTableSize; } + { return unitData()->stringTableSize; } private: + QQmlRefPointer m_compilationUnit; Heap::Module *m_module = nullptr; struct ResolveSetEntry @@ -365,7 +389,7 @@ private: }; ExecutableCompilationUnit(); - ExecutableCompilationUnit(CompiledData::CompilationUnit &&compilationUnit); + ExecutableCompilationUnit(QQmlRefPointer &&compilationUnit); ~ExecutableCompilationUnit(); const Value *resolveExportRecursively(QV4::String *exportName, diff --git a/src/qml/jsruntime/qv4module.cpp b/src/qml/jsruntime/qv4module.cpp index e044d285ee..f701529096 100644 --- a/src/qml/jsruntime/qv4module.cpp +++ b/src/qml/jsruntime/qv4module.cpp @@ -51,8 +51,8 @@ void Heap::Module::init(ExecutionEngine *engine, ExecutableCompilationUnit *modu { Scoped ic(valueScope, scope->internalClass); - for (uint i = 0; i < unit->data->importEntryTableSize; ++i) { - const CompiledData::ImportEntry &import = unit->data->importEntryTable()[i]; + for (uint i = 0; i < unit->unitData()->importEntryTableSize; ++i) { + const CompiledData::ImportEntry &import = unit->unitData()->importEntryTable()[i]; ic = ic->addMember(engine->identifierTable->asPropertyKey(unit->runtimeStrings[import.localName]), Attr_NotConfigurable); } scope->internalClass.set(engine, ic->d()); @@ -76,7 +76,7 @@ void Module::evaluate() unit->evaluateModuleRequests(); ExecutionEngine *v4 = engine(); - Function *moduleFunction = unit->runtimeFunctions[unit->data->indexOfRootFunction]; + Function *moduleFunction = unit->runtimeFunctions[unit->unitData()->indexOfRootFunction]; JSTypesStackFrame frame; frame.init(moduleFunction, nullptr, 0); frame.setupJSFrame(v4->jsStackTop, Value::undefinedValue(), d()->scope, diff --git a/src/qml/jsruntime/qv4resolvedtypereference.cpp b/src/qml/jsruntime/qv4resolvedtypereference.cpp index 4615a72eb1..7dcf2cd0b8 100644 --- a/src/qml/jsruntime/qv4resolvedtypereference.cpp +++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp @@ -88,8 +88,8 @@ bool ResolvedTypeReference::addToHash( } if (!m_compilationUnit) return false; - hash->addData({m_compilationUnit->data->md5Checksum, - sizeof(m_compilationUnit->data->md5Checksum)}); + hash->addData({m_compilationUnit->unitData()->md5Checksum, + sizeof(m_compilationUnit->unitData()->md5Checksum)}); return true; } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 34eefaadda..ab0e6ca813 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -133,7 +133,7 @@ Function *Script::function() return vmFunction; } -QV4::CompiledData::CompilationUnit Script::precompile( +QQmlRefPointer Script::precompile( QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, const QString &finalUrl, const QString &source, QList *reportedErrors, @@ -198,7 +198,10 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo : nullptr) { QQmlRefPointer jsUnit = QV4::ExecutableCompilationUnit::create( - QV4::CompiledData::CompilationUnit(cachedUnit->qmlData, cachedUnit->aotCompiledFunctions)); + QQmlRefPointer( + new QV4::CompiledData::CompilationUnit( + cachedUnit->qmlData, cachedUnit->aotCompiledFunctions), + QQmlRefPointer::Adopt)); return new QV4::Script(engine, qmlContext, jsUnit); } diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 26996ca2bc..64bccf1c47 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -65,7 +65,7 @@ struct Q_QML_EXPORT Script { Function *function(); - static QV4::CompiledData::CompilationUnit precompile( + static QQmlRefPointer precompile( QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, const QString &finalUrl, const QString &source, diff --git a/src/qml/qml/qqmlbuiltinfunctions.cpp b/src/qml/qml/qqmlbuiltinfunctions.cpp index c23e8f8914..855620922f 100644 --- a/src/qml/qml/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/qqmlbuiltinfunctions.cpp @@ -2174,7 +2174,7 @@ QString GlobalExtensions::currentTranslationContext(ExecutionEngine *engine) // The first non-empty source URL in the call stack determines the translation context. while (frame && context.isEmpty()) { if (ExecutableCompilationUnit *unit = frame->v4Function->executableCompilationUnit()) { - auto translationContextIndex = unit->data->translationContextIndex(); + auto translationContextIndex = unit->unitData()->translationContextIndex(); if (translationContextIndex) context = unit->stringAt(*translationContextIndex); if (!context.isEmpty()) diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp index 72bc3a7c12..6d7be99555 100644 --- a/src/qml/qml/qqmlscriptblob.cpp +++ b/src/qml/qml/qqmlscriptblob.cpp @@ -61,7 +61,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) return; } - QV4::CompiledData::CompilationUnit unit; + QQmlRefPointer unit; if (m_isModule) { QList diagnostics; @@ -117,7 +117,11 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) { initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create( - QV4::CompiledData::CompilationUnit(unit->qmlData, unit->aotCompiledFunctions, urlString(), finalUrlString()))); + QQmlRefPointer( + new QV4::CompiledData::CompilationUnit( + unit->qmlData, unit->aotCompiledFunctions, + urlString(), finalUrlString()), + QQmlRefPointer::Adopt))); } void QQmlScriptBlob::done() diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index f512a15512..03779b33eb 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -112,7 +112,7 @@ QQmlRefPointer QQmlTypeCompiler::compile() return nullptr; } - if (!document->javaScriptCompilationUnit.unitData()) { + if (!document->javaScriptCompilationUnit || !document->javaScriptCompilationUnit->unitData()) { // Compile JS binding expressions and signal handlers if necessary { // We can compile script strings ahead of time, but they must be compiled @@ -196,7 +196,7 @@ int QQmlTypeCompiler::registerConstant(QV4::ReturnedValue v) const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const { - return document->javaScriptCompilationUnit.unitData(); + return document->javaScriptCompilationUnit->unitData(); } const QQmlImports *QQmlTypeCompiler::imports() const diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index 3f688f646f..e69f21c930 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -100,7 +100,7 @@ bool QQmlTypeData::tryLoadFromDiskCache() } if (unit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation) { - restoreIR(std::move(*unit)); + restoreIR(unit->baseCompilationUnit()); return true; } @@ -651,7 +651,10 @@ void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *un loader.load(); m_document->jsModule.fileName = urlString(); m_document->jsModule.finalUrl = finalUrlString(); - m_document->javaScriptCompilationUnit = QV4::CompiledData::CompilationUnit(unit->qmlData, unit->aotCompiledFunctions); + m_document->javaScriptCompilationUnit + = QQmlRefPointer( + new QV4::CompiledData::CompilationUnit(unit->qmlData, unit->aotCompiledFunctions), + QQmlRefPointer::Adopt); continueLoadFromIR(); } @@ -686,14 +689,14 @@ bool QQmlTypeData::loadFromSource() return true; } -void QQmlTypeData::restoreIR(QV4::CompiledData::CompilationUnit &&unit) +void QQmlTypeData::restoreIR(const QQmlRefPointer &unit) { m_document.reset(new QmlIR::Document(isDebugging())); - QQmlIRLoader loader(unit.unitData(), m_document.data()); + QQmlIRLoader loader(unit->unitData(), m_document.data()); loader.load(); m_document->jsModule.fileName = urlString(); m_document->jsModule.finalUrl = finalUrlString(); - m_document->javaScriptCompilationUnit = std::move(unit); + m_document->javaScriptCompilationUnit = unit; continueLoadFromIR(); } @@ -809,8 +812,11 @@ void QQmlTypeData::compile(const QQmlRefPointer &typeNameCach { Q_ASSERT(m_compiledData.isNull()); - const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit.unitData() - && (m_document->javaScriptCompilationUnit.unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation); + const bool typeRecompilation = m_document + && m_document->javaScriptCompilationUnit + && m_document->javaScriptCompilationUnit->unitData() + && (m_document->javaScriptCompilationUnit->unitData()->flags + & QV4::CompiledData::Unit::PendingTypeCompilation); QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine()); QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache, dependencyHasher); diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h index 55704985e6..edc4db0636 100644 --- a/src/qml/qml/qqmltypedata_p.h +++ b/src/qml/qml/qqmltypedata_p.h @@ -85,7 +85,7 @@ protected: private: bool tryLoadFromDiskCache(); bool loadFromSource(); - void restoreIR(QV4::CompiledData::CompilationUnit &&unit); + void restoreIR(const QQmlRefPointer &unit); void continueLoadFromIR(); void resolveTypes(); QQmlError buildTypeResolutionCaches( diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp index 69d80283e3..6514caad6f 100644 --- a/src/qmlcompiler/qqmljscompiler.cpp +++ b/src/qmlcompiler/qqmljscompiler.cpp @@ -363,8 +363,8 @@ bool qCompileQmlFile(QmlIR::Document &irDocument, const QString &inputFileName, const quint32 saveFlags = QV4::CompiledData::Unit::StaticData | QV4::CompiledData::Unit::PendingTypeCompilation; - QV4::CompiledData::SaveableUnitPointer saveable(irDocument.javaScriptCompilationUnit.data, - saveFlags); + QV4::CompiledData::SaveableUnitPointer saveable( + irDocument.javaScriptCompilationUnit->unitData(), saveFlags); if (!saveFunction(saveable, aotFunctionsByIndex, &error->message)) return false; } @@ -373,7 +373,7 @@ bool qCompileQmlFile(QmlIR::Document &irDocument, const QString &inputFileName, bool qCompileJSFile(const QString &inputFileName, const QString &inputFileUrl, QQmlJSSaveFunction saveFunction, QQmlJSCompileError *error) { - QV4::CompiledData::CompilationUnit unit; + QQmlRefPointer unit; QString sourceCode; { @@ -397,7 +397,7 @@ bool qCompileJSFile(const QString &inputFileName, const QString &inputFileUrl, Q unit = QV4::Compiler::Codegen::compileModule(/*debugMode*/false, url, sourceCode, QDateTime(), &diagnostics); error->appendDiagnostics(inputFileName, diagnostics); - if (!unit.unitData()) + if (!unit || !unit->unitData()) return false; } else { QmlIR::Document irDocument(/*debugMode*/false); @@ -455,7 +455,8 @@ bool qCompileJSFile(const QString &inputFileName, const QString &inputFileUrl, Q } QQmlJSAotFunctionMap empty; - return saveFunction(QV4::CompiledData::SaveableUnitPointer(unit.data), empty, &error->message); + return saveFunction( + QV4::CompiledData::SaveableUnitPointer(unit->unitData()), empty, &error->message); } static const char *wrapCallCode = R"( diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 52979539a2..c24e413df9 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -351,7 +351,7 @@ void tst_qmlcachegen::signalHandlerParameters() }; QVERIFY(isStringIndexInStringTable(compilationUnit->objectAt(0)->signalAt(0)->parameterAt(0)->nameIndex)); - QVERIFY(!compilationUnit->dynamicStrings.isEmpty()); + QVERIFY(!compilationUnit->baseCompilationUnit()->dynamicStrings.isEmpty()); } } diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index acf03c51b7..8e424171b8 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -1432,7 +1432,7 @@ void tst_qqmlcomponent::loadFromQrc() QQmlComponentPrivate *p = QQmlComponentPrivate::get(&component); QVERIFY(p); QVERIFY(p->compilationUnit); - QVERIFY(p->compilationUnit->aotCompiledFunctions); + QVERIFY(p->compilationUnit->baseCompilationUnit()->aotCompiledFunctions); } void tst_qqmlcomponent::removeBinding() diff --git a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp index dbd7817749..6447e7ff9f 100644 --- a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp +++ b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp @@ -509,7 +509,7 @@ void tst_qqmljsscope::scriptIndices() QmlIR::Document document(false); // we need QmlIR information here QQmlJSScope::ConstPtr root = run(u"functionAndBindingIndices.qml"_s, &document); QVERIFY(root); - QVERIFY(document.javaScriptCompilationUnit.unitData()); + QVERIFY(document.javaScriptCompilationUnit->unitData()); // compare QQmlJSScope and QmlIR: @@ -756,8 +756,8 @@ void tst_qqmljsscope::compilationUnitsAreCompatible() QmlIR::Document document(false); // we need QmlIR information here QVERIFY(run(url, &document)); - QVERIFY(document.javaScriptCompilationUnit.unitData()); - getRuntimeInfoFromCompilationUnit(document.javaScriptCompilationUnit.unitData(), + QVERIFY(document.javaScriptCompilationUnit->unitData()); + getRuntimeInfoFromCompilationUnit(document.javaScriptCompilationUnit->unitData(), cachegenFunctions); if (QTest::currentTestFailed()) return; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 808f91cf59..b351df1a7d 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -2624,7 +2624,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode() memcpy(qmlUnit, readOnlyQmlUnit.data(), readOnlyQmlUnit->unitSize); qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData; - compilationUnit->setUnitData(qmlUnit); + compilationUnit->baseCompilationUnit()->setUnitData(qmlUnit); const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0); QCOMPARE(compilationUnit->stringAt(rootObject->inheritedTypeNameIndex), QString("MyTypeObject")); diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp index 6503920f96..97e3bcc472 100644 --- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp +++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp @@ -60,7 +60,7 @@ void tst_qqmltranslation::translation() QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine()); QQmlRefPointer typeData = engine->typeLoader.getType(context->baseUrl()); QVERIFY(!typeData->backupSourceCode().isValid()); - QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit(); + QV4::ExecutableCompilationUnit *compilationUnit = typeData->compilationUnit(); QVERIFY(compilationUnit); QSet compiledTranslations; @@ -73,7 +73,7 @@ void tst_qqmltranslation::translation() << QStringLiteral("emptyContext"); const QV4::CompiledData::Object *rootObject - = compilationUnit->qmlData->objectAt(/*root object*/0); + = compilationUnit->qmlData()->objectAt(/*root object*/0); const QV4::CompiledData::Binding *binding = rootObject->bindingTable(); for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) { const QString propertyName = compilationUnit->stringAt(binding->propertyNameIndex); @@ -125,11 +125,11 @@ void tst_qqmltranslation::idTranslation() QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine()); QQmlRefPointer typeData = engine->typeLoader.getType(context->baseUrl()); QVERIFY(!typeData->backupSourceCode().isValid()); - QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit(); + QV4::ExecutableCompilationUnit *compilationUnit = typeData->compilationUnit(); QVERIFY(compilationUnit); const QV4::CompiledData::Object *rootObject - = compilationUnit->qmlData->objectAt(/*root object*/0); + = compilationUnit->qmlData()->objectAt(/*root object*/0); const QV4::CompiledData::Binding *binding = rootObject->bindingTable(); for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) { const QString propertyName = compilationUnit->stringAt(binding->propertyNameIndex); diff --git a/tests/auto/toolsupport/tst_toolsupport.cpp b/tests/auto/toolsupport/tst_toolsupport.cpp index 486d760511..283b549d7c 100644 --- a/tests/auto/toolsupport/tst_toolsupport.cpp +++ b/tests/auto/toolsupport/tst_toolsupport.cpp @@ -78,7 +78,7 @@ void tst_toolsupport::offsets_data() = QTest::newRow("CompiledData::CompilationUnit::data") << pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::data); - data << 0 << 0; + data << 4 << 8; } { -- cgit v1.2.3