From e56eeee9902ffc341506040e637654b2b0451209 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 Jul 2018 10:40:41 +0200 Subject: Encapsulate the unit data in CompilationUnit This allows updating the constants table when the unit data is set / changes and removes the tie to the engine. Change-Id: Ice553650390589e30e18421c4e55422a55d0df89 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 2 +- src/qml/compiler/qqmlpropertyvalidator.cpp | 2 +- src/qml/compiler/qqmltypecompiler.cpp | 6 ++-- src/qml/compiler/qv4codegen.cpp | 5 +-- src/qml/compiler/qv4compileddata.cpp | 52 +++++++++++++++++++----------- src/qml/compiler/qv4compileddata_p.h | 7 ++-- src/qml/jsruntime/qv4runtime.cpp | 2 +- src/qml/qml/qqmlbinding.cpp | 2 +- src/qml/qml/qqmlcontext.cpp | 2 +- src/qml/qml/qqmlobjectcreator.cpp | 4 +-- src/qml/qml/qqmltypeloader.cpp | 32 +++++++++--------- src/qml/qml/qqmlvmemetaobject.cpp | 2 +- src/qml/types/qqmlconnections.cpp | 2 +- src/qml/types/qqmllistmodel.cpp | 6 ++-- 14 files changed, 73 insertions(+), 53 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 04a7854d56..0461299866 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1584,7 +1584,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4: char *data = (char*)malloc(totalSize); memcpy(data, jsUnit, unitSize); memset(data + unitSize, 0, totalSize - unitSize); - if (jsUnit != compilationUnit->data) + if (jsUnit != compilationUnit->unitData()) free(jsUnit); jsUnit = nullptr; diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 7daf2f1f2f..7ae88cf80c 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -49,7 +49,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c : enginePrivate(enginePrivate) , compilationUnit(compilationUnit) , imports(imports) - , qmlUnit(compilationUnit->data) + , qmlUnit(compilationUnit->unitData()) , resolvedTypes(compilationUnit->resolvedTypes) , propertyCaches(compilationUnit->propertyCaches) , bindingPropertyDataPerObject(&compilationUnit->bindingPropertyDataPerObject) diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 0d338c8b7e..6582a9ca6b 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -161,14 +161,14 @@ QQmlRefPointer QQmlTypeCompiler::compile() Q_ASSERT(document->javaScriptCompilationUnit); // The js unit owns the data and will free the qml unit. - document->javaScriptCompilationUnit->data = qmlUnit; + document->javaScriptCompilationUnit->setUnitData(qmlUnit); QQmlRefPointer compilationUnit = document->javaScriptCompilationUnit; compilationUnit = document->javaScriptCompilationUnit; compilationUnit->typeNameCache = typeNameCache; compilationUnit->resolvedTypes = resolvedTypes; compilationUnit->propertyCaches = std::move(m_propertyCaches); - Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->data->nObjects)); + Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->unitData()->nObjects)); if (errors.isEmpty()) return compilationUnit; @@ -209,7 +209,7 @@ int QQmlTypeCompiler::registerString(const QString &str) const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const { - return document->javaScriptCompilationUnit->data; + return document->javaScriptCompilationUnit->unitData(); } const QQmlImports *QQmlTypeCompiler::imports() const diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index b0e9d4ce66..c81ea09cce 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3534,9 +3534,10 @@ QList Codegen::errors() const QQmlRefPointer Codegen::generateCompilationUnit(bool generateUnitData) { - CompiledData::CompilationUnit *compilationUnit = new CompiledData::CompilationUnit; + CompiledData::Unit *unitData = nullptr; if (generateUnitData) - compilationUnit->data = jsUnitGenerator->generateUnit(); + unitData = jsUnitGenerator->generateUnit(); + CompiledData::CompilationUnit *compilationUnit = new CompiledData::CompilationUnit(unitData); QQmlRefPointer unit; unit.adopt(compilationUnit); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 0c81a5b3c6..a4c7c98642 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -64,6 +64,7 @@ #include #include #include +#include // generated by qmake: #include "qml_compile_hash_p.h" @@ -91,7 +92,7 @@ static_assert(sizeof(Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1, " CompilationUnit::CompilationUnit(const Unit *unitData) { - data = unitData; + setUnitData(unitData); } #ifndef V4_BOOTSTRAP @@ -101,6 +102,10 @@ CompilationUnit::~CompilationUnit() if (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) free(const_cast(data)); data = nullptr; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + delete [] constants; + constants = nullptr; +#endif } QString CompilationUnit::localCacheFilePath(const QUrl &url) @@ -175,16 +180,6 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) } } -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - Value *bigEndianConstants = new Value[data->constantTableSize]; - const quint64_le *littleEndianConstants = data->constants(); - for (uint i = 0; i < data->constantTableSize; ++i) - bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]); - constants = bigEndianConstants; -#else - constants = reinterpret_cast(data->constants()); -#endif - linkBackendToEngine(engine); static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); @@ -240,10 +235,6 @@ void CompilationUnit::unlink() runtimeClasses = nullptr; qDeleteAll(runtimeFunctions); runtimeFunctions.clear(); -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - delete [] constants; - constants = nullptr; -#endif } void CompilationUnit::markObjects(QV4::MarkStack *markStack) @@ -369,14 +360,18 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeS continue; const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; - QScopedValueRollback dataPtrChange(data, mappedUnit); + const Unit *oldData = data; + auto dataPtrRevert = qScopeGuard([this, oldData](){ + setUnitData(oldData); + }); + setUnitData(mappedUnit); if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) { *errorString = QStringLiteral("QML source file has moved to a different location."); continue; } - dataPtrChange.commit(); + dataPtrRevert.dismiss(); free(const_cast(oldDataPtr)); backingFile.reset(cacheFile.take()); return true; @@ -572,6 +567,27 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) return jsUnit; } +void CompilationUnit::setUnitData(const Unit *unitData) +{ + data = unitData; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + delete [] constants; +#endif + constants = nullptr; + if (!data) + return; + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + Value *bigEndianConstants = new Value[data->constantTableSize]; + const quint64_le *littleEndianConstants = data->constants(); + for (uint i = 0; i < data->constantTableSize; ++i) + bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]); + constants = bigEndianConstants; +#else + constants = reinterpret_cast(data->constants()); +#endif +} + QString Binding::valueAsString(const Unit *unit) const { switch (type) { @@ -697,7 +713,7 @@ bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engi hash->addData(createPropertyCache(engine)->checksum(&ok)); return ok; } - hash->addData(compilationUnit->data->md5Checksum, sizeof(compilationUnit->data->md5Checksum)); + hash->addData(compilationUnit->unitData()->md5Checksum, sizeof(compilationUnit->unitData()->md5Checksum)); return true; } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 5103c6901e..31e83e8f76 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -982,7 +982,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnitBase QV4::Heap::String **runtimeStrings = nullptr; // Array const Value* constants = nullptr; QV4::Value *runtimeRegularExpressions = nullptr; - const Unit *data = nullptr; QV4::Heap::InternalClass **runtimeClasses = nullptr; }; @@ -993,6 +992,7 @@ Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offs struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase { + const Unit *data = nullptr; public: CompilationUnit(const Unit *unitData = nullptr); #ifdef V4_BOOTSTRAP @@ -1019,7 +1019,10 @@ public: } // Called only when building QML, when we build the header for JS first and append QML data - QV4::CompiledData::Unit *createUnitData(QmlIR::Document *irDocument); + Unit *createUnitData(QmlIR::Document *irDocument); + + const Unit *unitData() const { return data; } + void setUnitData(const Unit *unitData); #ifndef V4_BOOTSTRAP QIntrusiveListNode nextCompilationUnit; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 8e982dae24..768d010bdf 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1512,7 +1512,7 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classIndex, const Value &superClass, const Value *computedNames) { const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit; - const QV4::CompiledData::Class *cls = unit->data->classAt(classIndex); + const QV4::CompiledData::Class *cls = unit->unitData()->classAt(classIndex); Scope scope(engine); ScopedObject protoParent(scope, engine->objectPrototype()); diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index a4b3f1f4e4..a791497ad6 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -358,7 +358,7 @@ public: if (!isAddedToObject() || hasError()) return; - const QString result = m_binding->valueAsString(m_compilationUnit->data); + const QString result = m_binding->valueAsString(m_compilationUnit->unitData()); Q_ASSERT(targetObject()); diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 3dcfa92416..2e37ed204d 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -845,7 +845,7 @@ void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointerdata->objectAt(componentObjectIndex)->nNamedObjectsInComponent; + idValueCount = typeCompilationUnit->unitData()->objectAt(componentObjectIndex)->nNamedObjectsInComponent; idValues = new ContextGuard[idValueCount]; } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index fb05201010..6f6065dc45 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -120,7 +120,7 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext) if (compilationUnit && !compilationUnit->engine) compilationUnit->linkToEngine(v4); - qmlUnit = compilationUnit->data; + qmlUnit = compilationUnit->unitData(); context = nullptr; _qobject = nullptr; _scopeObject = nullptr; @@ -1192,7 +1192,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( compilationUnit.data(), obj, typeRef->compilationUnit->fileName(), context->url())); - if (typeRef->compilationUnit->data->isSingleton()) + if (typeRef->compilationUnit->unitData()->isSingleton()) { recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex))); return nullptr; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 3340b96a21..9fa6027945 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2110,7 +2110,7 @@ bool QQmlTypeData::tryLoadFromDiskCache() } } - if (unit->data->flags & QV4::CompiledData::Unit::PendingTypeCompilation) { + if (unit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation) { restoreIR(unit); return true; } @@ -2132,8 +2132,8 @@ bool QQmlTypeData::tryLoadFromDiskCache() return false; // find the implicit import - for (quint32 i = 0; i < m_compiledData->data->nImports; ++i) { - const QV4::CompiledData::Import *import = m_compiledData->data->importAt(i); + for (quint32 i = 0; i < m_compiledData->unitData()->nImports; ++i) { + const QV4::CompiledData::Import *import = m_compiledData->unitData()->importAt(i); if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".") && import->qualifierIndex == 0 && import->majorVersion == -1 @@ -2149,8 +2149,8 @@ bool QQmlTypeData::tryLoadFromDiskCache() } } - for (int i = 0, count = m_compiledData->data->nImports; i < count; ++i) { - const QV4::CompiledData::Import *import = m_compiledData->data->importAt(i); + for (int i = 0, count = m_compiledData->unitData()->nImports; i < count; ++i) { + const QV4::CompiledData::Import *import = m_compiledData->unitData()->importAt(i); QList errors; if (!addImport(import, &errors)) { Q_ASSERT(errors.size()); @@ -2199,8 +2199,8 @@ static bool addTypeReferenceChecksumsToHash(const QListcompilationUnit(); - hash->addData(unit->data->md5Checksum, sizeof(unit->data->md5Checksum)); + const auto unit = typeRef.typeData->compilationUnit()->unitData(); + hash->addData(unit->md5Checksum, sizeof(unit->md5Checksum)); } else if (typeRef.type.isValid()) { const auto propertyCache = QQmlEnginePrivate::get(engine)->cache(typeRef.type.metaObject()); bool ok = false; @@ -2334,7 +2334,7 @@ void QQmlTypeData::done() { QQmlType type = QQmlMetaType::qmlType(finalUrl(), true); - if (m_compiledData && m_compiledData->data->flags & QV4::CompiledData::Unit::IsSingleton) { + if (m_compiledData && m_compiledData->unitData()->flags & QV4::CompiledData::Unit::IsSingleton) { if (!type.isValid()) { QQmlError error; error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent.")); @@ -2480,7 +2480,7 @@ bool QQmlTypeData::loadFromSource() void QQmlTypeData::restoreIR(QQmlRefPointer unit) { m_document.reset(new QmlIR::Document(isDebugging())); - QmlIR::IRLoader loader(unit->data, m_document.data()); + QmlIR::IRLoader loader(unit->unitData(), m_document.data()); loader.load(); m_document->jsModule.fileName = urlString(); m_document->jsModule.finalUrl = finalUrlString(); @@ -2587,7 +2587,7 @@ void QQmlTypeData::compile(const QQmlRefPointer &typeNameCach { Q_ASSERT(m_compiledData.isNull()); - const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit && m_document->javaScriptCompilationUnit->data->flags & QV4::CompiledData::Unit::PendingTypeCompilation; + const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit && 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); @@ -2859,7 +2859,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent QV4::ExecutionEngine *v4 = parentCtxt->engine->handle(); QV4::Scope scope(v4); - bool shared = m_precompiledScript->data->flags & QV4::CompiledData::Unit::IsSharedLibrary; + bool shared = m_precompiledScript->unitData()->flags & QV4::CompiledData::Unit::IsSharedLibrary; QQmlContextData *effectiveCtxt = parentCtxt; if (shared) @@ -3009,9 +3009,9 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit); - Q_ASSERT(!unit->data); + Q_ASSERT(!unit->unitData()); // The js unit owns the data and will free the qml unit. - unit->data = unitData; + unit->setUnitData(unitData); if ((!disableDiskCache() || forceDiskCache()) && !isDebugging()) { QString errorString; @@ -3076,7 +3076,7 @@ void QQmlScriptBlob::done() QString QQmlScriptBlob::stringAt(int index) const { - return m_scriptData->m_precompiledScript->data->stringAt(index); + return m_scriptData->m_precompiledScript->unitData()->stringAt(index); } void QQmlScriptBlob::scriptImported(const QQmlRefPointer &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) @@ -3100,8 +3100,8 @@ void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointerm_precompiledScript->data->flags & QV4::CompiledData::Unit::IsQml); - const QV4::CompiledData::Unit *qmlUnit = m_scriptData->m_precompiledScript->data; + Q_ASSERT(m_scriptData->m_precompiledScript->unitData()->flags & QV4::CompiledData::Unit::IsQml); + const QV4::CompiledData::Unit *qmlUnit = m_scriptData->m_precompiledScript->unitData(); QList errors; for (quint32 i = 0; i < qmlUnit->nImports; ++i) { diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 6bc0f0aa1e..7ba5d6356f 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -326,7 +326,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QQmlData::get(obj)->hasVMEMetaObject = true; if (compilationUnit && qmlObjectId >= 0) { - compiledObject = compilationUnit->data->objectAt(qmlObjectId); + compiledObject = compilationUnit->unitData()->objectAt(qmlObjectId); if (compiledObject->nProperties || compiledObject->nFunctions) { uint size = compiledObject->nProperties + compiledObject->nFunctions; diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 0cb6758008..75ed521108 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -276,7 +276,7 @@ void QQmlConnections::connectSignals() QQmlData *ddata = QQmlData::get(this); QQmlContextData *ctxtdata = ddata ? ddata->outerContext : nullptr; - const QV4::CompiledData::Unit *qmlUnit = d->compilationUnit->data; + const QV4::CompiledData::Unit *qmlUnit = d->compilationUnit->unitData(); for (const QV4::CompiledData::Binding *binding : qAsConst(d->bindings)) { Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script); QString propName = qmlUnit->stringAt(binding->propertyNameIndex); diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 39616251eb..503e5cb88c 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -313,7 +313,7 @@ QString StringOrTranslation::toString(const QQmlListModel *owner) const } if (!owner) return QString(); - return d.asT2()->valueAsString(owner->m_compilationUnit->data); + return d.asT2()->valueAsString(owner->m_compilationUnit->unitData()); } QString StringOrTranslation::asString() const @@ -2682,7 +2682,7 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointertype == QV4::CompiledData::Binding::Type_Script) { - QString scriptStr = binding->valueAsScriptString(compilationUnit->data); + QString scriptStr = binding->valueAsScriptString(compilationUnit->unitData()); if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) { QByteArray script = scriptStr.toUtf8(); bool ok; @@ -2797,7 +2797,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointerm_engine = qmlEngine(rv)->handle(); rv->m_compilationUnit = compilationUnit; - const QV4::CompiledData::Unit *qmlUnit = compilationUnit->data; + const QV4::CompiledData::Unit *qmlUnit = compilationUnit->unitData(); bool setRoles = false; -- cgit v1.2.3