From 7f7d87c68da4cb29b2b2b9c324c6863228da0c26 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 7 May 2019 12:47:33 +0200 Subject: Split CompiledData::CompilationUnit in two We need a CompilationUnit that only holds the data needed for compilation and another one that is executable by the runtime. Change-Id: I704d859ba028576a18460f5e3a59f210f64535d3 Reviewed-by: Simon Hausmann --- src/imports/statemachine/signaltransition.cpp | 6 +- src/imports/statemachine/signaltransition.h | 6 +- .../qmltooling/qmldbg_debugger/qv4debugjob.cpp | 2 +- src/qml/compiler/compiler.pri | 8 +- src/qml/compiler/qqmlirbuilder.cpp | 14 +- src/qml/compiler/qqmlirbuilder_p.h | 2 +- src/qml/compiler/qqmlirloader_p.h | 1 + src/qml/compiler/qqmlpropertyvalidator.cpp | 32 +- src/qml/compiler/qqmlpropertyvalidator_p.h | 6 +- src/qml/compiler/qqmltypecompiler.cpp | 19 +- src/qml/compiler/qqmltypecompiler_p.h | 15 +- src/qml/compiler/qv4codegen.cpp | 26 +- src/qml/compiler/qv4codegen_p.h | 5 +- src/qml/compiler/qv4compileddata.cpp | 742 +------------------ src/qml/compiler/qv4compileddata_p.h | 248 ++----- src/qml/compiler/qv4executablecompilationunit.cpp | 784 +++++++++++++++++++++ src/qml/compiler/qv4executablecompilationunit_p.h | 318 +++++++++ src/qml/debugger/qqmlprofiler_p.h | 15 +- src/qml/jsruntime/qv4context.cpp | 4 +- src/qml/jsruntime/qv4engine.cpp | 14 +- src/qml/jsruntime/qv4engine_p.h | 16 +- src/qml/jsruntime/qv4function.cpp | 13 +- src/qml/jsruntime/qv4function_p.h | 33 +- src/qml/jsruntime/qv4functionobject.cpp | 11 +- src/qml/jsruntime/qv4functionobject_p.h | 2 +- src/qml/jsruntime/qv4generatorobject.cpp | 2 +- src/qml/jsruntime/qv4module.cpp | 4 +- src/qml/jsruntime/qv4module_p.h | 4 +- src/qml/jsruntime/qv4profiling.cpp | 2 +- src/qml/jsruntime/qv4profiling_p.h | 20 +- src/qml/jsruntime/qv4runtime.cpp | 50 +- src/qml/jsruntime/qv4script.cpp | 18 +- src/qml/jsruntime/qv4script_p.h | 10 +- src/qml/jsruntime/qv4vme_moth.cpp | 10 +- src/qml/qml/qqmlbinding.cpp | 6 +- src/qml/qml/qqmlbinding_p.h | 2 +- src/qml/qml/qqmlcomponent.cpp | 3 +- src/qml/qml/qqmlcomponent.h | 7 +- src/qml/qml/qqmlcomponent_p.h | 2 +- src/qml/qml/qqmlcontext.cpp | 2 +- src/qml/qml/qqmlcontext_p.h | 6 +- src/qml/qml/qqmlcustomparser_p.h | 4 +- src/qml/qml/qqmldata_p.h | 8 +- src/qml/qml/qqmlengine.cpp | 6 +- src/qml/qml/qqmlengine_p.h | 6 +- src/qml/qml/qqmlincubator_p.h | 2 +- src/qml/qml/qqmljavascriptexpression.cpp | 4 +- src/qml/qml/qqmljavascriptexpression_p.h | 4 +- src/qml/qml/qqmlmetatype.cpp | 4 +- src/qml/qml/qqmlmetatype_p.h | 6 +- src/qml/qml/qqmlobjectcreator.cpp | 60 +- src/qml/qml/qqmlobjectcreator_p.h | 8 +- src/qml/qml/qqmlproperty_p.h | 1 + src/qml/qml/qqmltype.cpp | 4 +- src/qml/qml/qqmltypeloader.cpp | 77 +- src/qml/qml/qqmltypeloader_p.h | 19 +- src/qml/qml/qqmltypewrapper.cpp | 2 +- src/qml/qml/qqmlvmemetaobject.cpp | 2 +- src/qml/qml/qqmlvmemetaobject_p.h | 4 +- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 3 +- src/qml/types/qqmlconnections.cpp | 6 +- src/qml/types/qqmlconnections_p.h | 4 +- src/qmlmodels/qqmllistmodel.cpp | 18 +- src/qmlmodels/qqmllistmodel_p.h | 10 +- src/qmltest/quicktest.cpp | 11 +- .../designer/qquickdesignercustomparserobject.cpp | 4 +- .../designer/qquickdesignercustomparserobject_p.h | 4 +- src/quick/util/qquickpropertychanges.cpp | 16 +- src/quick/util/qquickpropertychanges_p.h | 6 +- .../qml/ecmascripttests/qjstest/test262runner.cpp | 2 +- tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 30 +- tests/auto/qml/qqmllanguage/testtypes.cpp | 6 +- tests/auto/qml/qqmllanguage/testtypes.h | 18 +- tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 6 +- .../qml/qqmltranslation/tst_qqmltranslation.cpp | 6 +- tools/qmlcachegen/qmlcachegen.cpp | 30 +- tools/qmljs/qmljs.cpp | 3 +- 77 files changed, 1594 insertions(+), 1300 deletions(-) create mode 100644 src/qml/compiler/qv4executablecompilationunit.cpp create mode 100644 src/qml/compiler/qv4executablecompilationunit_p.h diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp index 52dffe9004..468f2020c7 100644 --- a/src/imports/statemachine/signaltransition.cpp +++ b/src/imports/statemachine/signaltransition.cpp @@ -184,7 +184,7 @@ void SignalTransition::connectTriggered() m_signalExpression = expression; } -void SignalTransitionParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) +void SignalTransitionParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) { for (int ii = 0; ii < props.count(); ++ii) { const QV4::CompiledData::Binding *binding = props.at(ii); @@ -203,7 +203,9 @@ void SignalTransitionParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) +void SignalTransitionParser::applyBindings( + QObject *object, const QQmlRefPointer &compilationUnit, + const QList &bindings) { SignalTransition *st = qobject_cast(object); st->m_compilationUnit = compilationUnit; diff --git a/src/imports/statemachine/signaltransition.h b/src/imports/statemachine/signaltransition.h index 90e6f96fbc..f005c5e9b1 100644 --- a/src/imports/statemachine/signaltransition.h +++ b/src/imports/statemachine/signaltransition.h @@ -89,7 +89,7 @@ private: QJSValue m_signal; QQmlScriptString m_guard; bool m_complete; - QQmlRefPointer m_compilationUnit; + QQmlRefPointer m_compilationUnit; QList m_bindings; QQmlBoundSignalExpressionPointer m_signalExpression; }; @@ -97,8 +97,8 @@ private: class SignalTransitionParser : public QQmlCustomParser { public: - void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; - void applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) override; + void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; + void applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) override; }; QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp index b424ef9f6c..61fea96e2f 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp @@ -264,7 +264,7 @@ GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine) void GatherSourcesJob::run() { - for (QV4::CompiledData::CompilationUnit *unit : engine->compilationUnits) { + for (QV4::ExecutableCompilationUnit *unit : engine->compilationUnits) { QString fileName = unit->fileName(); if (!fileName.isEmpty()) sources.append(fileName); diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri index c15c45a1cb..3291d6e1f5 100644 --- a/src/qml/compiler/compiler.pri +++ b/src/qml/compiler/compiler.pri @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/qv4compilerscanfunctions_p.h \ $$PWD/qv4codegen_p.h \ $$PWD/qqmlirbuilder_p.h \ - $$PWD/qqmltypecompiler_p.h \ $$PWD/qv4instr_moth_p.h \ $$PWD/qv4bytecodehandler_p.h @@ -33,8 +32,8 @@ HEADERS += \ $$PWD/qqmltypecompiler_p.h \ $$PWD/qqmlpropertycachecreator_p.h \ $$PWD/qqmlpropertyvalidator_p.h \ - $$PWD/qv4compilationunitmapper_p.h - + $$PWD/qv4compilationunitmapper_p.h \ + $$PWD/qv4executablecompilationunit_p.h SOURCES += \ $$PWD/qqmlirloader.cpp \ @@ -42,7 +41,8 @@ SOURCES += \ $$PWD/qqmltypecompiler.cpp \ $$PWD/qqmlpropertycachecreator.cpp \ $$PWD/qqmlpropertyvalidator.cpp \ - $$PWD/qv4compilationunitmapper.cpp + $$PWD/qv4compilationunitmapper.cpp \ + $$PWD/qv4executablecompilationunit.cpp unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 41bdc3ae92..e63aa3b66d 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1548,15 +1548,12 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen output.jsGenerator.stringTable.registerString(output.jsModule.fileName); output.jsGenerator.stringTable.registerString(output.jsModule.finalUrl); - QQmlRefPointer compilationUnit = output.javaScriptCompilationUnit; - QV4::CompiledData::Unit *jsUnit = nullptr; - const bool finalize = !compilationUnit->data; // We may already have unit data if we're loading an ahead-of-time generated cache file. - if (!finalize) { - jsUnit = const_cast(compilationUnit->data); - output.javaScriptCompilationUnit->dynamicStrings = output.jsGenerator.stringTable.allStrings(); + if (output.javaScriptCompilationUnit.data) { + jsUnit = const_cast(output.javaScriptCompilationUnit.data); + output.javaScriptCompilationUnit.dynamicStrings = output.jsGenerator.stringTable.allStrings(); } else { QV4::CompiledData::Unit *createdUnit; jsUnit = createdUnit = output.jsGenerator.generateUnit(); @@ -1748,7 +1745,7 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen } } - if (finalize) { + if (!output.javaScriptCompilationUnit.data) { // Combine the qml data into the general unit data. jsUnit = static_cast(realloc(jsUnit, jsUnit->unitSize + totalSize)); jsUnit->offsetToQmlUnit = jsUnit->unitSize; @@ -1781,7 +1778,8 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen qDebug() << " " << totalStringSize << "bytes total strings"; } - compilationUnit->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 c937158a33..b49eaee420 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -379,7 +379,7 @@ struct Q_QML_PRIVATE_EXPORT Document QVector objects; QV4::Compiler::JSUnitGenerator jsGenerator; - QQmlRefPointer javaScriptCompilationUnit; + QV4::CompiledData::CompilationUnit javaScriptCompilationUnit; int registerString(const QString &str) { return jsGenerator.registerString(str); } QString stringAt(int index) const { return jsGenerator.stringForIndex(index); } diff --git a/src/qml/compiler/qqmlirloader_p.h b/src/qml/compiler/qqmlirloader_p.h index cf46ca3cb0..aa303c923f 100644 --- a/src/qml/compiler/qqmlirloader_p.h +++ b/src/qml/compiler/qqmlirloader_p.h @@ -52,6 +52,7 @@ // #include +#include QT_BEGIN_NAMESPACE diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 1812ad6546..5b0bd8858a 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE -QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer &compilationUnit) +QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer &compilationUnit) : enginePrivate(enginePrivate) , compilationUnit(compilationUnit) , imports(imports) @@ -339,7 +339,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) return noError; - QString value = binding->valueAsString(compilationUnit.data()); + QString value = compilationUnit->bindingValueAsString(binding); QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex()); bool ok; if (p.isFlagType()) { @@ -427,7 +427,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::Color: { bool ok = false; - QQmlStringConverters::rgbaFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: color expected")); } @@ -436,7 +436,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache #if QT_CONFIG(datestring) case QVariant::Date: { bool ok = false; - QQmlStringConverters::dateFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: date expected")); } @@ -444,7 +444,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::Time: { bool ok = false; - QQmlStringConverters::timeFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: time expected")); } @@ -452,7 +452,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::DateTime: { bool ok = false; - QQmlStringConverters::dateTimeFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: datetime expected")); } @@ -461,7 +461,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache #endif // datestring case QVariant::Point: { bool ok = false; - QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: point expected")); } @@ -469,7 +469,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::PointF: { bool ok = false; - QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: point expected")); } @@ -477,7 +477,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::Size: { bool ok = false; - QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: size expected")); } @@ -485,7 +485,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::SizeF: { bool ok = false; - QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: size expected")); } @@ -493,7 +493,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::Rect: { bool ok = false; - QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: rect expected")); } @@ -501,7 +501,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache break; case QVariant::RectF: { bool ok = false; - QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok); if (!ok) { return warnOrError(tr("Invalid property assignment: point expected")); } @@ -518,7 +518,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache float xp; float yp; } vec; - if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) { + if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) { return warnOrError(tr("Invalid property assignment: 2D vector expected")); } } @@ -529,7 +529,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache float yp; float zy; } vec; - if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) { + if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) { return warnOrError(tr("Invalid property assignment: 3D vector expected")); } } @@ -541,7 +541,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache float zy; float wp; } vec; - if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) { + if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) { return warnOrError(tr("Invalid property assignment: 4D vector expected")); } } @@ -553,7 +553,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache float yp; float zp; } vec; - if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) { + if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) { return warnOrError(tr("Invalid property assignment: quaternion expected")); } } diff --git a/src/qml/compiler/qqmlpropertyvalidator_p.h b/src/qml/compiler/qqmlpropertyvalidator_p.h index e9ae844ccb..8244b2df21 100644 --- a/src/qml/compiler/qqmlpropertyvalidator_p.h +++ b/src/qml/compiler/qqmlpropertyvalidator_p.h @@ -58,7 +58,7 @@ class QQmlPropertyValidator { Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator) public: - QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer &compilationUnit); + QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer &compilationUnit); QVector validate(); @@ -72,13 +72,13 @@ private: Q_REQUIRED_RESULT QVector recordError(const QV4::CompiledData::Location &location, const QString &description) const; Q_REQUIRED_RESULT QVector recordError(const QQmlCompileError &error) const; QString stringAt(int index) const { return compilationUnit->stringAt(index); } - QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const + QV4::ResolvedTypeReference *resolvedType(int id) const { return compilationUnit->resolvedType(id); } QQmlEnginePrivate *enginePrivate; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; const QQmlImports &imports; const QV4::CompiledData::Unit *qmlUnit; const QQmlPropertyCacheVector &propertyCaches; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 996b2f16ae..66320b8db9 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *parsedQML, const QQmlRefPointer &typeNameCache, - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) + QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) : resolvedTypes(resolvedTypeCache) , engine(engine) , typeData(typeData) @@ -66,7 +66,7 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *type { } -QQmlRefPointer QQmlTypeCompiler::compile() +QQmlRefPointer QQmlTypeCompiler::compile() { // Build property caches and VME meta object data @@ -134,7 +134,7 @@ QQmlRefPointer QQmlTypeCompiler::compile() return nullptr; } - if (!document->javaScriptCompilationUnit) { + if (!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 @@ -159,7 +159,9 @@ QQmlRefPointer QQmlTypeCompiler::compile() QmlIR::QmlUnitGenerator qmlGenerator; qmlGenerator.generate(*document, dependencyHasher); - QQmlRefPointer compilationUnit = document->javaScriptCompilationUnit; + QQmlRefPointer compilationUnit + = QV4::ExecutableCompilationUnit::create(std::move( + document->javaScriptCompilationUnit)); compilationUnit->typeNameCache = typeNameCache; compilationUnit->resolvedTypes = *resolvedTypes; compilationUnit->propertyCaches = std::move(m_propertyCaches); @@ -209,7 +211,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 @@ -253,11 +255,6 @@ const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const return &document->jsGenerator.stringTable; } -void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector &propertyData) -{ - document->javaScriptCompilationUnit->bindingPropertyDataPerObject = propertyData; -} - QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const { return object->bindingAsString(document, scriptIndex); @@ -857,7 +854,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent; if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) { - auto typeRef = new QV4::CompiledData::ResolvedTypeReference; + auto typeRef = new QV4::ResolvedTypeReference; typeRef->type = componentType; typeRef->majorVersion = componentType.majorVersion(); typeRef->minorVersion = componentType.minorVersion(); diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index a49b97453f..f588909c42 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -81,7 +81,7 @@ struct QQmlTypeCompiler public: QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer &typeNameCache, - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); // --- interface used by QQmlPropertyCacheCreator @@ -91,10 +91,10 @@ public: QString stringAt(int idx) const; QmlIR::PoolList::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); } QmlIR::PoolList::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); } - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr; + QV4::ResolvedTypeReferenceMap *resolvedTypes = nullptr; // --- - QQmlRefPointer compile(); + QQmlRefPointer compile(); QList compilationErrors() const { return errors; } void recordError(QQmlError error); @@ -118,7 +118,6 @@ public: QQmlJS::MemoryPool *memoryPool(); QStringRef newStringRef(const QString &string); const QV4::Compiler::StringTableGenerator *stringPool() const; - void setBindingPropertyDataPerObject(const QVector &propertyData); const QHash &customParserCache() const { return customParsers; } @@ -126,7 +125,7 @@ public: void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion); - QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const + QV4::ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes->value(id); } @@ -157,12 +156,12 @@ protected: void recordError(const QQmlCompileError &error) { compiler->recordError(error); } - QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const + QV4::ResolvedTypeReference *resolvedType(int id) const { return compiler->resolvedType(id); } bool containsResolvedType(int id) const { return compiler->resolvedTypes->contains(id); } - QV4::CompiledData::ResolvedTypeReferenceMap::iterator insertResolvedType( - int id, QV4::CompiledData::ResolvedTypeReference *value) + QV4::ResolvedTypeReferenceMap::iterator insertResolvedType( + int id, QV4::ResolvedTypeReference *value) { return compiler->resolvedTypes->insert(id, value); } QQmlTypeCompiler *compiler; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index edd479a0bd..d17d58588c 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3783,26 +3783,14 @@ QList Codegen::errors() const return _errors; } -QQmlRefPointer Codegen::generateCompilationUnit(bool generateUnitData) +QV4::CompiledData::CompilationUnit Codegen::generateCompilationUnit( + bool generateUnitData) { - CompiledData::Unit *unitData = nullptr; - if (generateUnitData) - unitData = jsUnitGenerator->generateUnit(); - CompiledData::CompilationUnit *compilationUnit = new CompiledData::CompilationUnit(unitData); - - QQmlRefPointer unit; - unit.adopt(compilationUnit); - return unit; -} - -QQmlRefPointer Codegen::createUnitForLoading() -{ - QQmlRefPointer result; - result.adopt(new CompiledData::CompilationUnit); - return result; + return QV4::CompiledData::CompilationUnit( + generateUnitData ? jsUnitGenerator->generateUnit() : nullptr); } -QQmlRefPointer Codegen::compileModule( +CompiledData::CompilationUnit Codegen::compileModule( bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList *diagnostics) { @@ -3817,7 +3805,7 @@ QQmlRefPointer Codegen::compileModule( *diagnostics = parser.diagnosticMessages(); if (!parsed) - return nullptr; + return CompiledData::CompilationUnit(); QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast(parser.rootNode()); if (!moduleNode) { @@ -3840,7 +3828,7 @@ QQmlRefPointer Codegen::compileModule( *diagnostics << errors; if (!errors.isEmpty()) - return nullptr; + return CompiledData::CompilationUnit(); return cg.generateCompilationUnit(); } diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 962ccc8562..8cf56b6cb7 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -684,9 +684,8 @@ public: Reference referenceForName(const QString &name, bool lhs, const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation()); - QQmlRefPointer generateCompilationUnit(bool generateUnitData = true); - static QQmlRefPointer createUnitForLoading(); - static QQmlRefPointer compileModule( + QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true); + static QV4::CompiledData::CompilationUnit compileModule( bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList *diagnostics); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 6e09eac977..091c29c8c7 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -39,34 +39,12 @@ #include "qv4compileddata_p.h" #include -#ifndef V4_BOOTSTRAP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qv4compilationunitmapper_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#endif #include #include #include #include #include +#include // generated by qmake: #include "qml_compile_hash_p.h" @@ -99,10 +77,6 @@ CompilationUnit::CompilationUnit(const Unit *unitData, const QString &fileName, CompilationUnit::~CompilationUnit() { -#ifndef V4_BOOTSTRAP - unlink(); -#endif - if (data) { if (data->qmlUnit() != qmlData) free(const_cast(qmlData)); @@ -126,582 +100,11 @@ CompilationUnit::~CompilationUnit() delete [] imports; imports = nullptr; } -#ifndef V4_BOOTSTRAP - -QString CompilationUnit::localCacheFilePath(const QUrl &url) -{ - const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url); - const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix(); - QCryptographicHash fileNameHash(QCryptographicHash::Sha1); - fileNameHash.addData(localSourcePath.toUtf8()); - QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/"); - QDir::root().mkpath(directory); - return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix; -} - -QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) -{ - this->engine = engine; - engine->compilationUnits.insert(this); - - Q_ASSERT(!runtimeStrings); - Q_ASSERT(data); - const quint32 stringCount = totalStringCount(); - runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*)); - // memset the strings to 0 in case a GC run happens while we're within the loop below - memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*)); - for (uint i = 0; i < stringCount; ++i) - runtimeStrings[i] = engine->newString(stringAt(i)); - - runtimeRegularExpressions = new QV4::Value[data->regexpTableSize]; - // memset the regexps to 0 in case a GC run happens while we're within the loop below - memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value)); - for (uint i = 0; i < data->regexpTableSize; ++i) { - const CompiledData::RegExp *re = data->regexpAt(i); - uint f = re->flags; - const CompiledData::RegExp::Flags flags = static_cast(f); - runtimeRegularExpressions[i] = QV4::RegExp::create(engine, stringAt(re->stringIndex), flags); - } - - if (data->lookupTableSize) { - runtimeLookups = new QV4::Lookup[data->lookupTableSize]; - memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup)); - const CompiledData::Lookup *compiledLookups = data->lookupTable(); - for (uint i = 0; i < data->lookupTableSize; ++i) { - QV4::Lookup *l = runtimeLookups + i; - - Lookup::Type type = Lookup::Type(uint(compiledLookups[i].type_and_flags)); - if (type == CompiledData::Lookup::Type_Getter) - l->getter = QV4::Lookup::getterGeneric; - else if (type == CompiledData::Lookup::Type_Setter) - l->setter = QV4::Lookup::setterGeneric; - else if (type == CompiledData::Lookup::Type_GlobalGetter) - l->globalGetter = QV4::Lookup::globalGetterGeneric; - else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter) - l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter; - l->nameIndex = compiledLookups[i].nameIndex; - } - } - - if (data->jsClassTableSize) { - runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); - // memset the regexps to 0 in case a GC run happens while we're within the loop below - memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); - for (uint i = 0; i < data->jsClassTableSize; ++i) { - int memberCount = 0; - const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount); - runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object); - for (int j = 0; j < memberCount; ++j, ++member) - runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); - } - } - - runtimeFunctions.resize(data->functionTableSize); - for (int i = 0 ;i < runtimeFunctions.size(); ++i) { - const QV4::CompiledData::Function *compiledFunction = data->functionAt(i); - runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction); - } - - Scope scope(engine); - Scoped ic(scope); - - runtimeBlocks.resize(data->blockTableSize); - for (int i = 0 ;i < runtimeBlocks.size(); ++i) { - const QV4::CompiledData::Block *compiledBlock = data->blockAt(i); - ic = engine->internalClasses(EngineBase::Class_CallContext); - - // first locals - const quint32_le *localsIndices = compiledBlock->localsTable(); - for (quint32 j = 0; j < compiledBlock->nLocals; ++j) - ic = ic->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]), Attr_NotConfigurable); - runtimeBlocks[i] = ic->d(); - } - - static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); - if (showCode) { - qDebug() << "=== Constant table"; - Moth::dumpConstantTable(constants, data->constantTableSize); - qDebug() << "=== String table"; - for (uint i = 0, end = totalStringCount(); i < end; ++i) - qDebug() << " " << i << ":" << runtimeStrings[i]->toQString(); - qDebug() << "=== Closure table"; - for (uint i = 0; i < data->functionTableSize; ++i) - qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString(); - qDebug() << "root function at index " << (data->indexOfRootFunction != -1 ? data->indexOfRootFunction : 0); - } - - if (data->indexOfRootFunction != -1) - return runtimeFunctions[data->indexOfRootFunction]; - else - return nullptr; -} - -Heap::Object *CompilationUnit::templateObjectAt(int index) const -{ - Q_ASSERT(index < int(data->templateObjectTableSize)); - if (!templateObjects.size()) - templateObjects.resize(data->templateObjectTableSize); - Heap::Object *o = templateObjects.at(index); - if (o) - return o; - - // create the template object - Scope scope(engine); - const CompiledData::TemplateObject *t = data->templateObjectAt(index); - Scoped a(scope, engine->newArrayObject(t->size)); - Scoped raw(scope, engine->newArrayObject(t->size)); - ScopedValue s(scope); - for (uint i = 0; i < t->size; ++i) { - s = runtimeStrings[t->stringIndexAt(i)]; - a->arraySet(i, s); - s = runtimeStrings[t->rawStringIndexAt(i)]; - raw->arraySet(i, s); - } - - ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1); - a->defineReadonlyProperty(QStringLiteral("raw"), raw); - ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1); - - templateObjects[index] = a->objectValue()->d(); - return templateObjects.at(index); -} - -void CompilationUnit::unlink() -{ - if (engine) - nextCompilationUnit.remove(); - - if (isRegisteredWithEngine) { - Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0)); - if (qmlEngine) - qmlEngine->unregisterInternalCompositeType(this); - QQmlMetaType::unregisterInternalCompositeType(this); - isRegisteredWithEngine = false; - } - - propertyCaches.clear(); - - if (runtimeLookups) { - for (uint i = 0; i < data->lookupTableSize; ++i) { - QV4::Lookup &l = runtimeLookups[i]; - if (l.getter == QV4::QObjectWrapper::lookupGetter) { - if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) - pc->release(); - } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) { - if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache) - pc->release(); - } - - if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) { - if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) - pc->release(); - } - } - } - - dependentScripts.clear(); - - typeNameCache = nullptr; - - qDeleteAll(resolvedTypes); - resolvedTypes.clear(); - - engine = nullptr; - qmlEngine = nullptr; - free(runtimeStrings); - runtimeStrings = nullptr; - delete [] runtimeLookups; - runtimeLookups = nullptr; - delete [] runtimeRegularExpressions; - runtimeRegularExpressions = nullptr; - free(runtimeClasses); - runtimeClasses = nullptr; - for (QV4::Function *f : qAsConst(runtimeFunctions)) - f->destroy(); - runtimeFunctions.clear(); -} - -void CompilationUnit::markObjects(QV4::MarkStack *markStack) -{ - if (runtimeStrings) { - for (uint i = 0, end = totalStringCount(); i < end; ++i) - if (runtimeStrings[i]) - runtimeStrings[i]->mark(markStack); - } - if (runtimeRegularExpressions) { - for (uint i = 0; i < data->regexpTableSize; ++i) - runtimeRegularExpressions[i].mark(markStack); - } - if (runtimeClasses) { - for (uint i = 0; i < data->jsClassTableSize; ++i) - if (runtimeClasses[i]) - runtimeClasses[i]->mark(markStack); - } - for (QV4::Function *f : qAsConst(runtimeFunctions)) - if (f && f->internalClass) - f->internalClass->mark(markStack); - for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks)) - if (c) - c->mark(markStack); - - for (QV4::Heap::Object *o : qAsConst(templateObjects)) - if (o) - o->mark(markStack); - - if (runtimeLookups) { - for (uint i = 0; i < data->lookupTableSize; ++i) - runtimeLookups[i].markObjects(markStack); - } - - if (m_module) - m_module->mark(markStack); -} - -IdentifierHash CompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex) -{ - IdentifierHash namedObjectCache(engine); - const CompiledData::Object *component = objectAt(componentObjectIndex); - const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable(); - for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) { - const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr); - namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id); - } - return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache); -} - -void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine) -{ - this->qmlEngine = qmlEngine; - - // Add to type registry of composites - if (propertyCaches.needsVMEMetaObject(/*root object*/0)) { - QQmlMetaType::registerInternalCompositeType(this); - qmlEngine->registerInternalCompositeType(this); - } else { - const QV4::CompiledData::Object *obj = objectAt(/*root object*/0); - auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); - Q_ASSERT(typeRef); - if (typeRef->compilationUnit) { - metaTypeId = typeRef->compilationUnit->metaTypeId; - listMetaTypeId = typeRef->compilationUnit->listMetaTypeId; - } else { - metaTypeId = typeRef->type.typeId(); - listMetaTypeId = typeRef->type.qListTypeId(); - } - } - - // Collect some data for instantiation later. - int bindingCount = 0; - int parserStatusCount = 0; - int objectCount = 0; - for (quint32 i = 0, count = this->objectCount(); i < count; ++i) { - const QV4::CompiledData::Object *obj = objectAt(i); - bindingCount += obj->nBindings; - if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { - if (typeRef->type.isValid()) { - if (typeRef->type.parserStatusCast() != -1) - ++parserStatusCount; - } - ++objectCount; - if (typeRef->compilationUnit) { - bindingCount += typeRef->compilationUnit->totalBindingsCount; - parserStatusCount += typeRef->compilationUnit->totalParserStatusCount; - objectCount += typeRef->compilationUnit->totalObjectCount; - } - } - } - - totalBindingsCount = bindingCount; - totalParserStatusCount = parserStatusCount; - totalObjectCount = objectCount; -} - -bool CompilationUnit::verifyChecksum(const DependentTypesHasher &dependencyHasher) const -{ - if (!dependencyHasher) { - for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) { - if (data->dependencyMD5Checksum[i] != 0) - return false; - } - return true; - } - const QByteArray checksum = dependencyHasher(); - return checksum.size() == sizeof(data->dependencyMD5Checksum) - && memcmp(data->dependencyMD5Checksum, checksum.constData(), - sizeof(data->dependencyMD5Checksum)) == 0; -} - -QStringList CompilationUnit::moduleRequests() const -{ - QStringList requests; - requests.reserve(data->moduleRequestTableSize); - for (uint i = 0; i < data->moduleRequestTableSize; ++i) - requests << stringAt(data->moduleRequestTable()[i]); - return requests; -} - -Heap::Module *CompilationUnit::instantiate(ExecutionEngine *engine) -{ - if (isESModule() && m_module) - return m_module; - - if (data->indexOfRootFunction < 0) - return nullptr; - - if (!this->engine) - linkToEngine(engine); - - Scope scope(engine); - Scoped module(scope, engine->memoryManager->allocate(engine, this)); - - if (isESModule()) - m_module = module->d(); - - for (const QString &request: moduleRequests()) { - auto dependentModuleUnit = engine->loadModule(QUrl(request), this); - if (engine->hasException) - return nullptr; - dependentModuleUnit->instantiate(engine); - } - - ScopedString importName(scope); - - const uint importCount = data->importEntryTableSize; - if (importCount > 0) { - imports = new const Value *[importCount]; - memset(imports, 0, importCount * sizeof(Value *)); - } - for (uint i = 0; i < importCount; ++i) { - const CompiledData::ImportEntry &entry = data->importEntryTable()[i]; - auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this); - importName = runtimeStrings[entry.importName]; - const Value *valuePtr = dependentModuleUnit->resolveExport(importName); - if (!valuePtr) { - QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference "); - referenceErrorMessage += importName->toQString(); - engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column); - return nullptr; - } - imports[i] = valuePtr; - } - - for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) { - const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i]; - auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this); - if (!dependentModuleUnit) - return nullptr; - - ScopedString importName(scope, runtimeStrings[entry.importName]); - if (!dependentModuleUnit->resolveExport(importName)) { - QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference "); - referenceErrorMessage += importName->toQString(); - engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column); - return nullptr; - } - } - - return module->d(); -} - -const Value *CompilationUnit::resolveExport(QV4::String *exportName) -{ - QVector resolveSet; - return resolveExportRecursively(exportName, &resolveSet); -} - -QStringList CompilationUnit::exportedNames() const -{ - QStringList names; - QVector exportNameSet; - getExportedNamesRecursively(&names, &exportNameSet); - names.sort(); - auto last = std::unique(names.begin(), names.end()); - names.erase(last, names.end()); - return names; -} - -const Value *CompilationUnit::resolveExportRecursively(QV4::String *exportName, QVector *resolveSet) -{ - if (!m_module) - return nullptr; - - for (const auto &entry: *resolveSet) - if (entry.module == this && entry.exportName->isEqualTo(exportName)) - return nullptr; - - (*resolveSet) << ResolveSetEntry(this, exportName); - - if (exportName->toQString() == QLatin1String("*")) - return &m_module->self; - - Scope scope(engine); - - if (auto localExport = lookupNameInExportTable(data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) { - ScopedString localName(scope, runtimeStrings[localExport->localName]); - uint index = m_module->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey()); - if (index == UINT_MAX) - return nullptr; - if (index >= m_module->scope->locals.size) - return imports[index - m_module->scope->locals.size]; - return &m_module->scope->locals[index]; - } - - if (auto indirectExport = lookupNameInExportTable(data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) { - auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(indirectExport->moduleRequest)), this); - if (!dependentModuleUnit) - return nullptr; - ScopedString importName(scope, runtimeStrings[indirectExport->importName]); - return dependentModuleUnit->resolveExportRecursively(importName, resolveSet); - } - - - if (exportName->toQString() == QLatin1String("default")) - return nullptr; - - const Value *starResolution = nullptr; - - for (uint i = 0; i < data->starExportEntryTableSize; ++i) { - const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i]; - auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this); - if (!dependentModuleUnit) - return nullptr; - - const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet); - // ### handle ambiguous - if (resolution) { - if (!starResolution) { - starResolution = resolution; - continue; - } - if (resolution != starResolution) - return nullptr; - } - } - - return starResolution; -} - -const ExportEntry *CompilationUnit::lookupNameInExportTable(const ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const -{ - const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize; - auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) { - return stringAt(lhs.exportName) < name->toQString(); - }); - if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString()) - return nullptr; - return matchingExport; -} - -void CompilationUnit::getExportedNamesRecursively(QStringList *names, QVector *exportNameSet, bool includeDefaultExport) const -{ - if (exportNameSet->contains(this)) - return; - exportNameSet->append(this); - - const auto append = [names, includeDefaultExport](const QString &name) { - if (!includeDefaultExport && name == QLatin1String("default")) - return; - names->append(name); - }; - - for (uint i = 0; i < data->localExportEntryTableSize; ++i) { - const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i]; - append(stringAt(entry.exportName)); - } - - for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) { - const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i]; - append(stringAt(entry.exportName)); - } - - for (uint i = 0; i < data->starExportEntryTableSize; ++i) { - const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i]; - auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this); - if (!dependentModuleUnit) - return; - dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false); - } -} -void CompilationUnit::evaluate() -{ - QV4::Scope scope(engine); - QV4::Scoped module(scope, m_module); - module->evaluate(); -} - -void CompilationUnit::evaluateModuleRequests() -{ - for (const QString &request: moduleRequests()) { - auto dependentModuleUnit = engine->loadModule(QUrl(request), this); - if (engine->hasException) - return; - dependentModuleUnit->evaluate(); - if (engine->hasException) - return; - } -} - -bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString) -{ - if (!QQmlFile::isLocalFile(url)) { - *errorString = QStringLiteral("File has to be a local file."); - return false; - } - - const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url); - QScopedPointer cacheFile(new CompilationUnitMapper()); - - const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) }; - for (const QString &cachePath : cachePaths) { - CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString); - if (!mappedUnit) - continue; - - const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; - 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; - } - - dataPtrRevert.dismiss(); - free(const_cast(oldDataPtr)); - backingFile.reset(cacheFile.take()); - return true; - } - - return false; -} - -#endif // V4_BOOTSTRAP - -#if defined(V4_BOOTSTRAP) -bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString) -#else -bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString) -#endif +bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString) const { errorString->clear(); -#if !defined(V4_BOOTSTRAP) - if (data->sourceTimeStamp == 0) { - *errorString = QStringLiteral("Missing time stamp for source file"); - return false; - } - - if (!QQmlFile::isLocalFile(unitUrl)) { - *errorString = QStringLiteral("File has to be a local file."); - return false; - } - const QString outputFileName = localCacheFilePath(unitUrl); -#endif - #if QT_CONFIG(temporaryfile) // Foo.qml -> Foo.qmlc QSaveFile cacheFile(outputFileName); @@ -767,51 +170,6 @@ void CompilationUnit::setUnitData(const Unit *unitData, const QmlUnit *qmlUnit, m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex); } -#ifndef V4_BOOTSTRAP -QString Binding::valueAsString(const CompilationUnit *unit) const -{ - switch (type) { - case Type_Script: - case Type_String: - return unit->stringAt(stringIndex); - case Type_Null: - return QStringLiteral("null"); - case Type_Boolean: - return value.b ? QStringLiteral("true") : QStringLiteral("false"); - case Type_Number: - return QString::number(valueAsNumber(unit->constants)); - case Type_Invalid: - return QString(); -#if !QT_CONFIG(translation) - case Type_TranslationById: - case Type_Translation: - return unit->stringAt(unit->unitData()->translations()[value.translationDataIndex].stringIndex); -#else - case Type_TranslationById: { - const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex]; - QByteArray id = unit->stringAt(translation.stringIndex).toUtf8(); - return qtTrId(id.constData(), translation.number); - } - case Type_Translation: { - const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex]; - // This code must match that in the qsTr() implementation - const QString &path = unit->fileName(); - int lastSlash = path.lastIndexOf(QLatin1Char('/')); - QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5) - : QStringRef(); - QByteArray contextUtf8 = context.toUtf8(); - QByteArray comment = unit->stringAt(translation.commentIndex).toUtf8(); - QByteArray text = unit->stringAt(translation.stringIndex).toUtf8(); - return QCoreApplication::translate(contextUtf8.constData(), text.constData(), - comment.constData(), translation.number); - } -#endif - default: - break; - } - return QString(); -} - //reverse of Lexer::singleEscape() QString Binding::escapedString(const QString &string) { @@ -855,98 +213,16 @@ QString Binding::escapedString(const QString &string) return tmp; } -QString Binding::valueAsScriptString(const CompilationUnit *unit) const -{ - if (type == Type_String) - return escapedString(unit->stringAt(stringIndex)); - else - return valueAsString(unit); -} - -/*! -Returns the property cache, if one alread exists. The cache is not referenced. -*/ -QQmlRefPointer ResolvedTypeReference::propertyCache() const -{ - if (type.isValid()) - return typePropertyCache; - else - return compilationUnit->rootPropertyCache(); -} - -/*! -Returns the property cache, creating one if it doesn't already exist. The cache is not referenced. -*/ -QQmlRefPointer ResolvedTypeReference::createPropertyCache(QQmlEngine *engine) -{ - if (typePropertyCache) { - return typePropertyCache; - } else if (type.isValid()) { - typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion); - return typePropertyCache; - } else { - return compilationUnit->rootPropertyCache(); - } -} - -bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine) -{ - if (type.isValid()) { - bool ok = false; - hash->addData(createPropertyCache(engine)->checksum(&ok)); - return ok; - } - if (!compilationUnit) - return false; - hash->addData(compilationUnit->unitData()->md5Checksum, sizeof(compilationUnit->unitData()->md5Checksum)); - return true; -} - -template -bool qtTypeInherits(const QMetaObject *mo) { - while (mo) { - if (mo == &T::staticMetaObject) - return true; - mo = mo->superClass(); - } - return false; -} - -void ResolvedTypeReference::doDynamicTypeCheck() -{ - const QMetaObject *mo = nullptr; - if (typePropertyCache) - mo = typePropertyCache->firstCppMetaObject(); - else if (type.isValid()) - mo = type.metaObject(); - else if (compilationUnit) - mo = compilationUnit->rootPropertyCache()->firstCppMetaObject(); - isFullyDynamicType = qtTypeInherits(mo); -} - -bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const -{ - for (auto it = constBegin(), end = constEnd(); it != end; ++it) { - if (!it.value()->addToHash(hash, engine)) - return false; - } - - return true; -} - -#endif - -void CompilationUnit::destroy() +void CompilationUnit::unlink() { -#if !defined(V4_BOOTSTRAP) - if (qmlEngine) - QQmlEnginePrivate::deleteInEngineThread(qmlEngine, this); - else -#endif - delete this; + free(runtimeStrings); + runtimeStrings = nullptr; + delete [] runtimeRegularExpressions; + runtimeRegularExpressions = nullptr; + free(runtimeClasses); + runtimeClasses = nullptr; } - void Unit::generateChecksum() { #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 4a90c841bb..9301939bff 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -65,11 +65,6 @@ #include #include #include -#ifndef V4_BOOTSTRAP -#include -#include -#include "private/qintrusivelist_p.h" -#endif QT_BEGIN_NAMESPACE @@ -101,7 +96,6 @@ struct Module; struct Function; class EvalISelFactory; -class CompilationUnitMapper; namespace CompiledData { @@ -528,10 +522,6 @@ struct Q_QML_PRIVATE_EXPORT Binding bool isTranslationBinding() const { return type == Type_Translation || type == Type_TranslationById; } bool evaluatesToString() const { return type == Type_String || isTranslationBinding(); } -#ifndef V4_BOOTSTRAP - QString valueAsString(const CompilationUnit *unit) const; - QString valueAsScriptString(const CompilationUnit *unit) const; -#endif double valueAsNumber(const Value *constantTable) const { if (type != Type_Number) @@ -1053,17 +1043,6 @@ struct TypeReferenceMap : QHash } }; -#ifndef V4_BOOTSTRAP -struct ResolvedTypeReference; -// map from name index -// While this could be a hash, a map is chosen here to provide a stable -// order, which is used to calculating a check-sum on dependent meta-objects. -struct ResolvedTypeReferenceMap: public QMap -{ - bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const; -}; -#endif - using DependentTypesHasher = std::function; // index is per-object binding index @@ -1073,6 +1052,30 @@ typedef QVector BindingPropertyData; struct Q_QML_PRIVATE_EXPORT CompilationUnitBase { + Q_DISABLE_COPY(CompilationUnitBase) + + CompilationUnitBase() = default; + ~CompilationUnitBase() = default; + + CompilationUnitBase(CompilationUnitBase &&other) noexcept { *this = std::move(other); } + + CompilationUnitBase &operator=(CompilationUnitBase &&other) noexcept + { + if (this != &other) { + runtimeStrings = other.runtimeStrings; + other.runtimeStrings = nullptr; + constants = other.constants; + other.constants = nullptr; + runtimeRegularExpressions = other.runtimeRegularExpressions; + other.runtimeRegularExpressions = nullptr; + runtimeClasses = other.runtimeClasses; + other.runtimeClasses = nullptr; + imports = other.imports; + other.imports = nullptr; + } + return *this; + } + // pointers either to data->constants() or little-endian memory copy. QV4::Heap::String **runtimeStrings = nullptr; // Array const Value* constants = nullptr; @@ -1088,30 +1091,42 @@ Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offs Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeClasses) == offsetof(CompilationUnitBase, runtimeRegularExpressions) + sizeof(const Value *)); Q_STATIC_ASSERT(offsetof(CompilationUnitBase, imports) == offsetof(CompilationUnitBase, runtimeClasses) + sizeof(const Value *)); -struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase +struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase { + Q_DISABLE_COPY(CompilationUnit) + const Unit *data = nullptr; const QmlUnit *qmlData = nullptr; QStringList dynamicStrings; public: + using CompiledObject = CompiledData::Object; + CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString()); ~CompilationUnit(); - void addref() + CompilationUnit(CompilationUnit &&other) noexcept { - Q_ASSERT(refCount.load() > 0); - refCount.ref(); + *this = std::move(other); } - void release() - { - Q_ASSERT(refCount.load() > 0); - if (!refCount.deref()) - destroy(); - } - int count() const + CompilationUnit &operator=(CompilationUnit &&other) noexcept { - return refCount.load(); + if (this != &other) { + data = other.data; + other.data = nullptr; + qmlData = other.qmlData; + other.qmlData = nullptr; + dynamicStrings = std::move(other.dynamicStrings); + other.dynamicStrings.clear(); + m_fileName = std::move(other.m_fileName); + other.m_fileName.clear(); + m_finalUrlString = std::move(other.m_finalUrlString); + other.m_finalUrlString.clear(); + m_module = other.m_module; + other.m_module = nullptr; + CompilationUnitBase::operator=(std::move(other)); + } + return *this; } const Unit *unitData() const { return data; } @@ -1125,185 +1140,24 @@ public: return data->stringAtInternal(index); } -#ifndef V4_BOOTSTRAP - QIntrusiveListNode nextCompilationUnit; - ExecutionEngine *engine = nullptr; - QQmlEnginePrivate *qmlEngine = nullptr; // only used in QML environment for composite types, not in plain QJSEngine case. - - // 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. - // - // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code - // They are _not_ intercepted and thus represent the "logical" name for the code. - QString fileName() const { return m_fileName; } QString finalUrlString() const { return m_finalUrlString; } - QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; } - QUrl finalUrl() const - { - if (m_finalUrl.isNull) - m_finalUrl = QUrl(finalUrlString()); - return m_finalUrl; - } - - QV4::Lookup *runtimeLookups = nullptr; - QVector runtimeFunctions; - QVector runtimeBlocks; - mutable QVector templateObjects; - mutable QQmlNullableValue m_url; - mutable QQmlNullableValue m_finalUrl; - - // QML specific fields - QQmlPropertyCacheVector propertyCaches; - QQmlRefPointer rootPropertyCache() const { return propertyCaches.at(/*root object*/0); } - - QQmlRefPointer typeNameCache; - - // index is object index. This allows fast access to the - // property data when initializing bindings, avoiding expensive - // lookups by string (property name). - QVector bindingPropertyDataPerObject; - - // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects - // this is initialized on-demand by QQmlContextData - QHash namedObjectsPerComponentCache; - inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex); - - void finalizeCompositeType(QQmlEnginePrivate *qmlEngine); - - int totalBindingsCount = 0; // Number of bindings used in this type - int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses - int totalObjectCount = 0; // Number of objects explicitly instantiated - - QVector> dependentScripts; - ResolvedTypeReferenceMap resolvedTypes; - ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } - - bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const; - - int metaTypeId = -1; - int listMetaTypeId = -1; - bool isRegisteredWithEngine = false; - QScopedPointer backingFile; + Heap::Module *module() const { return m_module; } + void setModule(Heap::Module *module) { m_module = module; } - // --- interface for QQmlPropertyCacheCreator - typedef Object CompiledObject; - int objectCount() const { return qmlData->nObjects; } - const Object *objectAt(int index) const { return qmlData->objectAt(index); } - int importCount() const { return qmlData->nImports; } - const Import *importAt(int index) const { return qmlData->importAt(index); } - - Heap::Object *templateObjectAt(int index) const; - - struct FunctionIterator - { - FunctionIterator(const Unit *unit, const Object *object, int index) : unit(unit), object(object), index(index) {} - const Unit *unit; - const Object *object; - int index; - - const Function *operator->() const { return unit->functionAt(object->functionOffsetTable()[index]); } - void operator++() { ++index; } - bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; } - bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; } - }; - FunctionIterator objectFunctionsBegin(const Object *object) const { return FunctionIterator(data, object, 0); } - FunctionIterator objectFunctionsEnd(const Object *object) const { return FunctionIterator(data, object, object->nFunctions); } - // --- - - bool isESModule() const { return data->flags & Unit::IsESModule; } - bool isSharedLibrary() const { return data->flags & Unit::IsSharedLibrary; } - QStringList moduleRequests() const; - Heap::Module *instantiate(ExecutionEngine *engine); - const Value *resolveExport(QV4::String *exportName); - QStringList exportedNames() const; - void evaluate(); - void evaluateModuleRequests(); - - QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); void unlink(); - void markObjects(MarkStack *markStack); - - bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString); - - static QString localCacheFilePath(const QUrl &url); - -protected: - quint32 totalStringCount() const - { return data->stringTableSize; } -#endif - private: - void destroy(); - - struct ResolveSetEntry - { - ResolveSetEntry() {} - ResolveSetEntry(CompilationUnit *module, QV4::String *exportName) - : module(module), exportName(exportName) {} - CompilationUnit *module = nullptr; - QV4::String *exportName = nullptr; - }; - - const Value *resolveExportRecursively(QV4::String *exportName, QVector *resolveSet); - const ExportEntry *lookupNameInExportTable(const ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const; - void getExportedNamesRecursively(QStringList *names, QVector *exportNameSet, bool includeDefaultExport = true) const; - QString m_fileName; // initialized from data->sourceFileIndex QString m_finalUrlString; // initialized from data->finalUrlIndex - QAtomicInt refCount = 1; - - Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex); - Heap::Module *m_module = nullptr; public: -#if defined(V4_BOOTSTRAP) - bool saveToDisk(const QString &outputFileName, QString *errorString); -#else - bool saveToDisk(const QUrl &unitUrl, QString *errorString); -#endif -}; - -#ifndef V4_BOOTSTRAP -struct ResolvedTypeReference -{ - ResolvedTypeReference() - : majorVersion(0) - , minorVersion(0) - , isFullyDynamicType(false) - {} - - QQmlType type; - QQmlRefPointer typePropertyCache; - QQmlRefPointer compilationUnit; - - int majorVersion; - int minorVersion; - // Types such as QQmlPropertyMap can add properties dynamically at run-time and - // therefore cannot have a property cache installed when instantiated. - bool isFullyDynamicType; - - QQmlRefPointer propertyCache() const; - QQmlRefPointer createPropertyCache(QQmlEngine *); - bool addToHash(QCryptographicHash *hash, QQmlEngine *engine); - - void doDynamicTypeCheck(); + bool saveToDisk(const QString &outputFileName, QString *errorString) const; }; -IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex) -{ - auto it = namedObjectsPerComponentCache.find(componentObjectIndex); - if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end())) - return createNamedObjectsPerComponent(componentObjectIndex); - return *it; -} -#endif // V4_BOOTSTRAP - } // CompiledData namespace } // QV4 namespace diff --git a/src/qml/compiler/qv4executablecompilationunit.cpp b/src/qml/compiler/qv4executablecompilationunit.cpp new file mode 100644 index 0000000000..432e0c5e37 --- /dev/null +++ b/src/qml/compiler/qv4executablecompilationunit.cpp @@ -0,0 +1,784 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4executablecompilationunit_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QV4 { + +ExecutableCompilationUnit::ExecutableCompilationUnit() = default; + +ExecutableCompilationUnit::ExecutableCompilationUnit( + CompiledData::CompilationUnit &&compilationUnit) + : CompiledData::CompilationUnit(std::move(compilationUnit)) +{} + +ExecutableCompilationUnit::~ExecutableCompilationUnit() +{ + unlink(); +} + +QString ExecutableCompilationUnit::localCacheFilePath(const QUrl &url) +{ + const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url); + const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix(); + QCryptographicHash fileNameHash(QCryptographicHash::Sha1); + fileNameHash.addData(localSourcePath.toUtf8()); + QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/"); + QDir::root().mkpath(directory); + return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix; +} + +QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine) +{ + this->engine = engine; + engine->compilationUnits.insert(this); + + Q_ASSERT(!runtimeStrings); + Q_ASSERT(data); + const quint32 stringCount = totalStringCount(); + runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*)); + // memset the strings to 0 in case a GC run happens while we're within the loop below + memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*)); + for (uint i = 0; i < stringCount; ++i) + runtimeStrings[i] = engine->newString(stringAt(i)); + + runtimeRegularExpressions + = new QV4::Value[data->regexpTableSize]; + // memset the regexps to 0 in case a GC run happens while we're within the loop below + memset(runtimeRegularExpressions, 0, + data->regexpTableSize * sizeof(QV4::Value)); + for (uint i = 0; i < data->regexpTableSize; ++i) { + const CompiledData::RegExp *re = data->regexpAt(i); + uint f = re->flags; + const CompiledData::RegExp::Flags flags = static_cast(f); + runtimeRegularExpressions[i] = QV4::RegExp::create( + engine, stringAt(re->stringIndex), flags); + } + + if (data->lookupTableSize) { + runtimeLookups = new QV4::Lookup[data->lookupTableSize]; + memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup)); + const CompiledData::Lookup *compiledLookups = data->lookupTable(); + for (uint i = 0; i < data->lookupTableSize; ++i) { + QV4::Lookup *l = runtimeLookups + i; + + CompiledData::Lookup::Type type + = CompiledData::Lookup::Type(uint(compiledLookups[i].type_and_flags)); + if (type == CompiledData::Lookup::Type_Getter) + l->getter = QV4::Lookup::getterGeneric; + else if (type == CompiledData::Lookup::Type_Setter) + l->setter = QV4::Lookup::setterGeneric; + else if (type == CompiledData::Lookup::Type_GlobalGetter) + l->globalGetter = QV4::Lookup::globalGetterGeneric; + else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter) + l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter; + l->nameIndex = compiledLookups[i].nameIndex; + } + } + + if (data->jsClassTableSize) { + runtimeClasses + = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize + * sizeof(QV4::Heap::InternalClass *)); + // memset the regexps to 0 in case a GC run happens while we're within the loop below + memset(runtimeClasses, 0, + data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); + for (uint i = 0; i < data->jsClassTableSize; ++i) { + int memberCount = 0; + const CompiledData::JSClassMember *member + = data->jsClassAt(i, &memberCount); + runtimeClasses[i] + = engine->internalClasses(QV4::ExecutionEngine::Class_Object); + for (int j = 0; j < memberCount; ++j, ++member) + runtimeClasses[i] + = runtimeClasses[i]->addMember( + engine->identifierTable->asPropertyKey( + runtimeStrings[member->nameOffset]), + member->isAccessor + ? QV4::Attr_Accessor + : QV4::Attr_Data); + } + } + + runtimeFunctions.resize(data->functionTableSize); + for (int i = 0 ;i < runtimeFunctions.size(); ++i) { + const QV4::CompiledData::Function *compiledFunction = data->functionAt(i); + runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction); + } + + Scope scope(engine); + Scoped ic(scope); + + runtimeBlocks.resize(data->blockTableSize); + for (int i = 0 ;i < runtimeBlocks.size(); ++i) { + const QV4::CompiledData::Block *compiledBlock = data->blockAt(i); + ic = engine->internalClasses(EngineBase::Class_CallContext); + + // first locals + const quint32_le *localsIndices = compiledBlock->localsTable(); + for (quint32 j = 0; j < compiledBlock->nLocals; ++j) + ic = ic->addMember( + engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]), + Attr_NotConfigurable); + runtimeBlocks[i] = ic->d(); + } + + static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); + if (showCode) { + qDebug() << "=== Constant table"; + Moth::dumpConstantTable(constants, data->constantTableSize); + qDebug() << "=== String table"; + for (uint i = 0, end = totalStringCount(); i < end; ++i) + qDebug() << " " << i << ":" << runtimeStrings[i]->toQString(); + qDebug() << "=== Closure table"; + for (uint i = 0; i < data->functionTableSize; ++i) + qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString(); + qDebug() << "root function at index " + << (data->indexOfRootFunction != -1 + ? data->indexOfRootFunction : 0); + } + + if (data->indexOfRootFunction != -1) + return runtimeFunctions[data->indexOfRootFunction]; + else + return nullptr; +} + +Heap::Object *ExecutableCompilationUnit::templateObjectAt(int index) const +{ + Q_ASSERT(index < int(data->templateObjectTableSize)); + if (!templateObjects.size()) + templateObjects.resize(data->templateObjectTableSize); + Heap::Object *o = templateObjects.at(index); + if (o) + return o; + + // create the template object + Scope scope(engine); + const CompiledData::TemplateObject *t = data->templateObjectAt(index); + Scoped a(scope, engine->newArrayObject(t->size)); + Scoped raw(scope, engine->newArrayObject(t->size)); + ScopedValue s(scope); + for (uint i = 0; i < t->size; ++i) { + s = runtimeStrings[t->stringIndexAt(i)]; + a->arraySet(i, s); + s = runtimeStrings[t->rawStringIndexAt(i)]; + raw->arraySet(i, s); + } + + ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1); + a->defineReadonlyProperty(QStringLiteral("raw"), raw); + ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1); + + templateObjects[index] = a->objectValue()->d(); + return templateObjects.at(index); +} + +void ExecutableCompilationUnit::unlink() +{ + if (engine) + nextCompilationUnit.remove(); + + if (isRegisteredWithEngine) { + Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0)); + if (qmlEngine) + qmlEngine->unregisterInternalCompositeType(this); + QQmlMetaType::unregisterInternalCompositeType(this); + isRegisteredWithEngine = false; + } + + propertyCaches.clear(); + + if (runtimeLookups) { + for (uint i = 0; i < data->lookupTableSize; ++i) { + QV4::Lookup &l = runtimeLookups[i]; + if (l.getter == QV4::QObjectWrapper::lookupGetter) { + if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) + pc->release(); + } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) { + if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache) + pc->release(); + } + + if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) { + if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) + pc->release(); + } + } + } + + dependentScripts.clear(); + + typeNameCache = nullptr; + + qDeleteAll(resolvedTypes); + resolvedTypes.clear(); + + engine = nullptr; + qmlEngine = nullptr; + + delete [] runtimeLookups; + runtimeLookups = nullptr; + + for (QV4::Function *f : qAsConst(runtimeFunctions)) + f->destroy(); + runtimeFunctions.clear(); + + CompiledData::CompilationUnit::unlink(); +} + +void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack) +{ + if (runtimeStrings) { + for (uint i = 0, end = totalStringCount(); i < end; ++i) + if (runtimeStrings[i]) + runtimeStrings[i]->mark(markStack); + } + if (runtimeRegularExpressions) { + for (uint i = 0; i < data->regexpTableSize; ++i) + runtimeRegularExpressions[i].mark(markStack); + } + if (runtimeClasses) { + for (uint i = 0; i < data->jsClassTableSize; ++i) + if (runtimeClasses[i]) + runtimeClasses[i]->mark(markStack); + } + for (QV4::Function *f : qAsConst(runtimeFunctions)) + if (f && f->internalClass) + f->internalClass->mark(markStack); + for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks)) + if (c) + c->mark(markStack); + + for (QV4::Heap::Object *o : qAsConst(templateObjects)) + if (o) + o->mark(markStack); + + if (runtimeLookups) { + for (uint i = 0; i < data->lookupTableSize; ++i) + runtimeLookups[i].markObjects(markStack); + } + + if (auto mod = module()) + mod->mark(markStack); +} + +IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex) +{ + IdentifierHash namedObjectCache(engine); + const CompiledData::Object *component = objectAt(componentObjectIndex); + const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable(); + for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) { + const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr); + namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id); + } + return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache); +} + +void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine) +{ + this->qmlEngine = qmlEngine; + + // Add to type registry of composites + if (propertyCaches.needsVMEMetaObject(/*root object*/0)) { + QQmlMetaType::registerInternalCompositeType(this); + qmlEngine->registerInternalCompositeType(this); + } else { + const QV4::CompiledData::Object *obj = objectAt(/*root object*/0); + auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); + Q_ASSERT(typeRef); + if (typeRef->compilationUnit) { + metaTypeId = typeRef->compilationUnit->metaTypeId; + listMetaTypeId = typeRef->compilationUnit->listMetaTypeId; + } else { + metaTypeId = typeRef->type.typeId(); + listMetaTypeId = typeRef->type.qListTypeId(); + } + } + + // Collect some data for instantiation later. + int bindingCount = 0; + int parserStatusCount = 0; + int objectCount = 0; + for (quint32 i = 0, count = this->objectCount(); i < count; ++i) { + const QV4::CompiledData::Object *obj = objectAt(i); + bindingCount += obj->nBindings; + if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { + if (typeRef->type.isValid()) { + if (typeRef->type.parserStatusCast() != -1) + ++parserStatusCount; + } + ++objectCount; + if (typeRef->compilationUnit) { + bindingCount += typeRef->compilationUnit->totalBindingsCount; + parserStatusCount += typeRef->compilationUnit->totalParserStatusCount; + objectCount += typeRef->compilationUnit->totalObjectCount; + } + } + } + + totalBindingsCount = bindingCount; + totalParserStatusCount = parserStatusCount; + totalObjectCount = objectCount; +} + +bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const +{ + if (!dependencyHasher) { + for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) { + if (data->dependencyMD5Checksum[i] != 0) + return false; + } + return true; + } + const QByteArray checksum = dependencyHasher(); + return checksum.size() == sizeof(data->dependencyMD5Checksum) + && memcmp(data->dependencyMD5Checksum, checksum.constData(), + sizeof(data->dependencyMD5Checksum)) == 0; +} + +QStringList ExecutableCompilationUnit::moduleRequests() const +{ + QStringList requests; + requests.reserve(data->moduleRequestTableSize); + for (uint i = 0; i < data->moduleRequestTableSize; ++i) + requests << stringAt(data->moduleRequestTable()[i]); + return requests; +} + +Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine) +{ + if (isESModule() && module()) + return module(); + + if (data->indexOfRootFunction < 0) + return nullptr; + + if (!this->engine) + linkToEngine(engine); + + Scope scope(engine); + Scoped module(scope, engine->memoryManager->allocate(engine, this)); + + if (isESModule()) + setModule(module->d()); + + for (const QString &request: moduleRequests()) { + auto dependentModuleUnit = engine->loadModule(QUrl(request), this); + if (engine->hasException) + return nullptr; + dependentModuleUnit->instantiate(engine); + } + + ScopedString importName(scope); + + const uint importCount = data->importEntryTableSize; + if (importCount > 0) { + imports = new const Value *[importCount]; + memset(imports, 0, importCount * sizeof(Value *)); + } + for (uint i = 0; i < importCount; ++i) { + const CompiledData::ImportEntry &entry = data->importEntryTable()[i]; + auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this); + importName = runtimeStrings[entry.importName]; + const Value *valuePtr = dependentModuleUnit->resolveExport(importName); + if (!valuePtr) { + QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference "); + referenceErrorMessage += importName->toQString(); + engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column); + return nullptr; + } + imports[i] = valuePtr; + } + + for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) { + const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i]; + auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this); + if (!dependentModuleUnit) + return nullptr; + + ScopedString importName(scope, runtimeStrings[entry.importName]); + if (!dependentModuleUnit->resolveExport(importName)) { + QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference "); + referenceErrorMessage += importName->toQString(); + engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column); + return nullptr; + } + } + + return module->d(); +} + +const Value *ExecutableCompilationUnit::resolveExportRecursively( + QV4::String *exportName, QVector *resolveSet) +{ + if (!module()) + return nullptr; + + for (const auto &entry: *resolveSet) + if (entry.module == this && entry.exportName->isEqualTo(exportName)) + return nullptr; + + (*resolveSet) << ResolveSetEntry(this, exportName); + + if (exportName->toQString() == QLatin1String("*")) + return &module()->self; + + Scope scope(engine); + + if (auto localExport = lookupNameInExportTable( + data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) { + ScopedString localName(scope, runtimeStrings[localExport->localName]); + uint index = module()->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey()); + if (index == UINT_MAX) + return nullptr; + if (index >= module()->scope->locals.size) + return imports[index - module()->scope->locals.size]; + return &module()->scope->locals[index]; + } + + if (auto indirectExport = lookupNameInExportTable( + data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) { + auto dependentModuleUnit = engine->loadModule(urlAt(indirectExport->moduleRequest), this); + if (!dependentModuleUnit) + return nullptr; + ScopedString importName(scope, runtimeStrings[indirectExport->importName]); + return dependentModuleUnit->resolveExportRecursively(importName, resolveSet); + } + + + if (exportName->toQString() == QLatin1String("default")) + return nullptr; + + const Value *starResolution = nullptr; + + for (uint i = 0; i < data->starExportEntryTableSize; ++i) { + const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i]; + auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this); + if (!dependentModuleUnit) + return nullptr; + + const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet); + // ### handle ambiguous + if (resolution) { + if (!starResolution) { + starResolution = resolution; + continue; + } + if (resolution != starResolution) + return nullptr; + } + } + + return starResolution; +} + +const CompiledData::ExportEntry *ExecutableCompilationUnit::lookupNameInExportTable( + const CompiledData::ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const +{ + const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize; + auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) { + return stringAt(lhs.exportName) < name->toQString(); + }); + if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString()) + return nullptr; + return matchingExport; +} + +void ExecutableCompilationUnit::getExportedNamesRecursively( + QStringList *names, QVector *exportNameSet, + bool includeDefaultExport) const +{ + if (exportNameSet->contains(this)) + return; + exportNameSet->append(this); + + const auto append = [names, includeDefaultExport](const QString &name) { + if (!includeDefaultExport && name == QLatin1String("default")) + return; + names->append(name); + }; + + for (uint i = 0; i < data->localExportEntryTableSize; ++i) { + const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i]; + append(stringAt(entry.exportName)); + } + + for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) { + const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i]; + append(stringAt(entry.exportName)); + } + + for (uint i = 0; i < data->starExportEntryTableSize; ++i) { + const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i]; + auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this); + if (!dependentModuleUnit) + return; + dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false); + } +} + +void ExecutableCompilationUnit::evaluate() +{ + QV4::Scope scope(engine); + QV4::Scoped mod(scope, module()); + mod->evaluate(); +} + +void ExecutableCompilationUnit::evaluateModuleRequests() +{ + for (const QString &request: moduleRequests()) { + auto dependentModuleUnit = engine->loadModule(QUrl(request), this); + if (engine->hasException) + return; + dependentModuleUnit->evaluate(); + if (engine->hasException) + return; + } +} + +bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString) +{ + if (!QQmlFile::isLocalFile(url)) { + *errorString = QStringLiteral("File has to be a local file."); + return false; + } + + const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url); + QScopedPointer cacheFile(new CompilationUnitMapper()); + + const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) }; + for (const QString &cachePath : cachePaths) { + CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString); + if (!mappedUnit) + continue; + + const CompiledData::Unit * const oldDataPtr + = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data + : nullptr; + const CompiledData::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; + } + + dataPtrRevert.dismiss(); + free(const_cast(oldDataPtr)); + backingFile.reset(cacheFile.take()); + return true; + } + + return false; +} + +bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString) +{ + if (data->sourceTimeStamp == 0) { + *errorString = QStringLiteral("Missing time stamp for source file"); + return false; + } + + if (!QQmlFile::isLocalFile(unitUrl)) { + *errorString = QStringLiteral("File has to be a local file."); + return false; + } + + return CompilationUnit::saveToDisk(localCacheFilePath(unitUrl), errorString); +} + +/*! +Returns the property cache, if one alread exists. The cache is not referenced. +*/ +QQmlRefPointer ResolvedTypeReference::propertyCache() const +{ + if (type.isValid()) + return typePropertyCache; + else + return compilationUnit->rootPropertyCache(); +} + +/*! +Returns the property cache, creating one if it doesn't already exist. The cache is not referenced. +*/ +QQmlRefPointer ResolvedTypeReference::createPropertyCache(QQmlEngine *engine) +{ + if (typePropertyCache) { + return typePropertyCache; + } else if (type.isValid()) { + typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion); + return typePropertyCache; + } else { + return compilationUnit->rootPropertyCache(); + } +} + +bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine) +{ + if (type.isValid()) { + bool ok = false; + hash->addData(createPropertyCache(engine)->checksum(&ok)); + return ok; + } + if (!compilationUnit) + return false; + hash->addData(compilationUnit->data->md5Checksum, + sizeof(compilationUnit->data->md5Checksum)); + return true; +} + +template +bool qtTypeInherits(const QMetaObject *mo) { + while (mo) { + if (mo == &T::staticMetaObject) + return true; + mo = mo->superClass(); + } + return false; +} + +void ResolvedTypeReference::doDynamicTypeCheck() +{ + const QMetaObject *mo = nullptr; + if (typePropertyCache) + mo = typePropertyCache->firstCppMetaObject(); + else if (type.isValid()) + mo = type.metaObject(); + else if (compilationUnit) + mo = compilationUnit->rootPropertyCache()->firstCppMetaObject(); + isFullyDynamicType = qtTypeInherits(mo); +} + +bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const +{ + for (auto it = constBegin(), end = constEnd(); it != end; ++it) { + if (!it.value()->addToHash(hash, engine)) + return false; + } + + return true; +} + +QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const +{ + using namespace CompiledData; + switch (binding->type) { + case Binding::Type_Script: + case Binding::Type_String: + return stringAt(binding->stringIndex); + case Binding::Type_Null: + return QStringLiteral("null"); + case Binding::Type_Boolean: + return binding->value.b ? QStringLiteral("true") : QStringLiteral("false"); + case Binding::Type_Number: + return QString::number(binding->valueAsNumber(constants)); + case Binding::Type_Invalid: + return QString(); +#if !QT_CONFIG(translation) + case Binding::Type_TranslationById: + case Binding::Type_Translation: + return unit->stringAt( + unit->data->translations()[binding->value.translationDataIndex].stringIndex); +#else + case Binding::Type_TranslationById: { + const TranslationData &translation + = data->translations()[binding->value.translationDataIndex]; + QByteArray id = stringAt(translation.stringIndex).toUtf8(); + return qtTrId(id.constData(), translation.number); + } + case Binding::Type_Translation: { + const TranslationData &translation + = data->translations()[binding->value.translationDataIndex]; + // This code must match that in the qsTr() implementation + const QString &path = fileName(); + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5) + : QStringRef(); + QByteArray contextUtf8 = context.toUtf8(); + QByteArray comment = stringAt(translation.commentIndex).toUtf8(); + QByteArray text = stringAt(translation.stringIndex).toUtf8(); + return QCoreApplication::translate(contextUtf8.constData(), text.constData(), + comment.constData(), translation.number); + } +#endif + default: + break; + } + return QString(); +} + +QString ExecutableCompilationUnit::bindingValueAsScriptString( + const CompiledData::Binding *binding) const +{ + return (binding->type == CompiledData::Binding::Type_String) + ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex)) + : bindingValueAsString(binding); +} + +} // namespace QV4 + +QT_END_NAMESPACE diff --git a/src/qml/compiler/qv4executablecompilationunit_p.h b/src/qml/compiler/qv4executablecompilationunit_p.h new file mode 100644 index 0000000000..dd3918cc84 --- /dev/null +++ b/src/qml/compiler/qv4executablecompilationunit_p.h @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QV4EXECUTABLECOMPILATIONUNIT_P_H +#define QV4EXECUTABLECOMPILATIONUNIT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlEnginePrivate; +namespace QV4 { + +class CompilationUnitMapper; +struct ResolvedTypeReference; +// map from name index +// While this could be a hash, a map is chosen here to provide a stable +// order, which is used to calculating a check-sum on dependent meta-objects. +struct ResolvedTypeReferenceMap: public QMap +{ + bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const; +}; + +class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit, + public QQmlRefCount +{ + Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit) +public: + friend class QQmlRefPointer; + + static QQmlRefPointer create( + CompiledData::CompilationUnit &&compilationUnit) + { + return QQmlRefPointer( + new ExecutableCompilationUnit(std::move(compilationUnit)), + QQmlRefPointer::Adopt); + } + + static QQmlRefPointer create() + { + return QQmlRefPointer( + new ExecutableCompilationUnit, + QQmlRefPointer::Adopt); + } + + QIntrusiveListNode nextCompilationUnit; + ExecutionEngine *engine = nullptr; + QQmlEnginePrivate *qmlEngine = nullptr; // only used in QML environment for composite types, not in plain QJSEngine case. + + // 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. + // + // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code + // They are _not_ intercepted and thus represent the "logical" name for the code. + + QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; } + QUrl finalUrl() const + { + if (m_finalUrl.isNull) + m_finalUrl = QUrl(finalUrlString()); + return m_finalUrl; + } + + QV4::Lookup *runtimeLookups = nullptr; + QVector runtimeFunctions; + QVector runtimeBlocks; + mutable QVector templateObjects; + mutable QQmlNullableValue m_url; + mutable QQmlNullableValue m_finalUrl; + + // QML specific fields + QQmlPropertyCacheVector propertyCaches; + QQmlRefPointer rootPropertyCache() const { return propertyCaches.at(/*root object*/0); } + + QQmlRefPointer typeNameCache; + + // index is object index. This allows fast access to the + // property data when initializing bindings, avoiding expensive + // lookups by string (property name). + QVector bindingPropertyDataPerObject; + + // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects + // this is initialized on-demand by QQmlContextData + QHash namedObjectsPerComponentCache; + inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex); + + void finalizeCompositeType(QQmlEnginePrivate *qmlEngine); + + int totalBindingsCount = 0; // Number of bindings used in this type + int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses + int totalObjectCount = 0; // Number of objects explicitly instantiated + + QVector> dependentScripts; + ResolvedTypeReferenceMap resolvedTypes; + ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } + + bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const; + + int metaTypeId = -1; + int listMetaTypeId = -1; + bool isRegisteredWithEngine = false; + + QScopedPointer backingFile; + + // --- interface for QQmlPropertyCacheCreator + using CompiledObject = CompiledData::Object; + using CompiledFunction = CompiledData::Function; + + int objectCount() const { return qmlData->nObjects; } + const CompiledObject *objectAt(int index) const + { + return qmlData->objectAt(index); + } + + int importCount() const { return qmlData->nImports; } + const CompiledData::Import *importAt(int index) const + { + return qmlData->importAt(index); + } + + Heap::Object *templateObjectAt(int index) const; + + struct FunctionIterator + { + FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index) + : unit(unit), object(object), index(index) {} + const CompiledData::Unit *unit; + const CompiledObject *object; + int index; + + const CompiledFunction *operator->() const + { + return unit->functionAt(object->functionOffsetTable()[index]); + } + + void operator++() { ++index; } + bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; } + bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; } + }; + + FunctionIterator objectFunctionsBegin(const CompiledObject *object) const + { + return FunctionIterator(data, object, 0); + } + + FunctionIterator objectFunctionsEnd(const CompiledObject *object) const + { + return FunctionIterator(data, object, object->nFunctions); + } + + bool isESModule() const + { + return data->flags & CompiledData::Unit::IsESModule; + } + + bool isSharedLibrary() const + { + return data->flags & CompiledData::Unit::IsSharedLibrary; + } + + QStringList moduleRequests() const; + Heap::Module *instantiate(ExecutionEngine *engine); + const Value *resolveExport(QV4::String *exportName) + { + QVector resolveSet; + return resolveExportRecursively(exportName, &resolveSet); + } + + QStringList exportedNames() const + { + QStringList names; + QVector exportNameSet; + getExportedNamesRecursively(&names, &exportNameSet); + names.sort(); + auto last = std::unique(names.begin(), names.end()); + names.erase(last, names.end()); + return names; + } + + void evaluate(); + void evaluateModuleRequests(); + + QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); + void unlink(); + + void markObjects(MarkStack *markStack); + + bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString); + + static QString localCacheFilePath(const QUrl &url); + bool saveToDisk(const QUrl &unitUrl, QString *errorString); + + QString bindingValueAsString(const CompiledData::Binding *binding) const; + QString bindingValueAsScriptString(const CompiledData::Binding *binding) const; + +protected: + quint32 totalStringCount() const + { return data->stringTableSize; } + +private: + struct ResolveSetEntry + { + ResolveSetEntry() {} + ResolveSetEntry(ExecutableCompilationUnit *module, QV4::String *exportName) + : module(module), exportName(exportName) {} + ExecutableCompilationUnit *module = nullptr; + QV4::String *exportName = nullptr; + }; + + ExecutableCompilationUnit(); + ExecutableCompilationUnit(CompiledData::CompilationUnit &&compilationUnit); + ~ExecutableCompilationUnit(); + + const Value *resolveExportRecursively(QV4::String *exportName, + QVector *resolveSet); + + QUrl urlAt(int index) const { return QUrl(stringAt(index)); } + + Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex); + const CompiledData::ExportEntry *lookupNameInExportTable( + const CompiledData::ExportEntry *firstExportEntry, int tableSize, + QV4::String *name) const; + + void getExportedNamesRecursively( + QStringList *names, QVector *exportNameSet, + bool includeDefaultExport = true) const; +}; + +struct ResolvedTypeReference +{ + ResolvedTypeReference() + : majorVersion(0) + , minorVersion(0) + , isFullyDynamicType(false) + {} + + QQmlType type; + QQmlRefPointer typePropertyCache; + QQmlRefPointer compilationUnit; + + int majorVersion; + int minorVersion; + // Types such as QQmlPropertyMap can add properties dynamically at run-time and + // therefore cannot have a property cache installed when instantiated. + bool isFullyDynamicType; + + QQmlRefPointer propertyCache() const; + QQmlRefPointer createPropertyCache(QQmlEngine *); + bool addToHash(QCryptographicHash *hash, QQmlEngine *engine); + + void doDynamicTypeCheck(); +}; + +IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex) +{ + auto it = namedObjectsPerComponentCache.find(componentObjectIndex); + if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end())) + return createNamedObjectsPerComponent(componentObjectIndex); + return *it; +} + +} // namespace QV4 + +QT_END_NAMESPACE + +#endif // QV4EXECUTABLECOMPILATIONUNIT_P_H diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index d01e2bc429..d3eedab1c6 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -171,10 +171,11 @@ public: : Location(ref->sourceLocation()), locationType(Binding), sent(false) { function = ref; - function->compilationUnit->addref(); + function->executableCompilationUnit()->addref(); } - RefLocation(QV4::CompiledData::CompilationUnit *ref, const QUrl &url, const QV4::CompiledData::Object *obj, const QString &type) + RefLocation(QV4::ExecutableCompilationUnit *ref, const QUrl &url, + const QV4::CompiledData::Object *obj, const QString &type) : Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url), locationType(Creating), sent(false) { @@ -230,7 +231,7 @@ public: switch (locationType) { case Binding: - function->compilationUnit->addref(); + function->executableCompilationUnit()->addref(); break; case Creating: unit->addref(); @@ -254,7 +255,7 @@ public: switch (locationType) { case Binding: - function->compilationUnit->release(); + function->executableCompilationUnit()->release(); break; case Creating: unit->release(); @@ -284,7 +285,7 @@ public: RangeType locationType; union { QV4::Function *function; - QV4::CompiledData::CompilationUnit *unit; + QV4::ExecutableCompilationUnit *unit; QQmlBoundSignalExpression *boundSignal; QQmlDataBlob *blob; void *something; @@ -356,7 +357,7 @@ public: } void updateCreating(const QV4::CompiledData::Object *obj, - QV4::CompiledData::CompilationUnit *ref, + QV4::ExecutableCompilationUnit *ref, const QUrl &url, const QString &type) { quintptr locationId(id(obj)); @@ -492,7 +493,7 @@ public: Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange()); } - void update(QV4::CompiledData::CompilationUnit *ref, const QV4::CompiledData::Object *obj, + void update(QV4::ExecutableCompilationUnit *ref, const QV4::CompiledData::Object *obj, const QString &typeName, const QUrl &url) { profiler->updateCreating(obj, ref, url, typeName); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index b3bcfe21d5..130727378d 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -60,7 +60,7 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b { Function *function = frame->v4Function; - Heap::InternalClass *ic = function->compilationUnit->runtimeBlocks.at(blockIndex); + Heap::InternalClass *ic = function->executableCompilationUnit()->runtimeBlocks.at(blockIndex); uint nLocals = ic->size; size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals; @@ -76,7 +76,7 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b c->locals.size = nLocals; c->locals.alloc = nLocals; - c->setupLocalTemporalDeadZone(function->compilationUnit->unitData()->blockAt(blockIndex)); + c->setupLocalTemporalDeadZone(function->executableCompilationUnit()->unitData()->blockAt(blockIndex)); return c; } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index b04a879c7f..cd77ebd22a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1743,7 +1743,7 @@ ReturnedValue ExecutionEngine::global() return globalObject->asReturnedValue(); } -QQmlRefPointer ExecutionEngine::compileModule(const QUrl &url) +QQmlRefPointer ExecutionEngine::compileModule(const QUrl &url) { QFile f(QQmlFile::urlToLocalFileOrQrc(url)); if (!f.open(QIODevice::ReadOnly)) { @@ -1760,7 +1760,8 @@ QQmlRefPointer ExecutionEngine::compileModule(con } -QQmlRefPointer ExecutionEngine::compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp) +QQmlRefPointer ExecutionEngine::compileModule( + const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp) { QList diagnostics; auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(), @@ -1774,10 +1775,11 @@ QQmlRefPointer ExecutionEngine::compileModule(con << ": warning: " << m.message; } } - return unit; + + return ExecutableCompilationUnit::create(std::move(unit)); } -void ExecutionEngine::injectModule(const QQmlRefPointer &moduleUnit) +void ExecutionEngine::injectModule(const QQmlRefPointer &moduleUnit) { // Injection can happen from the QML type loader thread for example, but instantiation and // evaluation must be limited to the ExecutionEngine's thread. @@ -1785,7 +1787,7 @@ void ExecutionEngine::injectModule(const QQmlRefPointerfinalUrl(), moduleUnit); } -QQmlRefPointer ExecutionEngine::moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer) const +QQmlRefPointer ExecutionEngine::moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer) const { QUrl url = QQmlTypeLoader::normalize(_url); if (referrer) @@ -1798,7 +1800,7 @@ QQmlRefPointer ExecutionEngine::moduleForUrl(cons return *existingModule; } -QQmlRefPointer ExecutionEngine::loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer) +QQmlRefPointer ExecutionEngine::loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer) { QUrl url = QQmlTypeLoader::normalize(_url); if (referrer) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 0d113754c0..f8ac0e0268 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -64,6 +64,7 @@ #include "qv4function_p.h" #include +#include namespace WTF { class BumpPointerAllocator; @@ -489,7 +490,7 @@ public: Symbol *symbol_unscopables() const { return reinterpret_cast(jsSymbols + Symbol_unscopables); } Symbol *symbol_revokableProxy() const { return reinterpret_cast(jsSymbols + Symbol_revokableProxy); } - QIntrusiveList compilationUnits; + QIntrusiveList compilationUnits; quint32 m_engineId; @@ -698,14 +699,15 @@ public: double localTZA = 0.0; // local timezone, initialized at startup - QQmlRefPointer compileModule(const QUrl &url); - QQmlRefPointer compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp); + QQmlRefPointer compileModule(const QUrl &url); + QQmlRefPointer compileModule( + const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp); mutable QMutex moduleMutex; - QHash> modules; - void injectModule(const QQmlRefPointer &moduleUnit); - QQmlRefPointer moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const; - QQmlRefPointer loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr); + QHash> modules; + void injectModule(const QQmlRefPointer &moduleUnit); + QQmlRefPointer moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const; + QQmlRefPointer loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr); private: #if QT_CONFIG(qml_debug) diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index debdf23d27..d870cec68a 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -73,7 +73,8 @@ ReturnedValue Function::call(const Value *thisObject, const Value *argv, int arg return result; } -Function *Function::create(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function) +Function *Function::create(ExecutionEngine *engine, ExecutableCompilationUnit *unit, + const CompiledData::Function *function) { return new Function(engine, unit, function); } @@ -83,7 +84,8 @@ void Function::destroy() delete this; } -Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function) +Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit, + const CompiledData::Function *function) : FunctionData(unit) , compiledFunction(function) , codeData(function->code()) @@ -146,8 +148,11 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QListlocalsTable(); - for (quint32 i = 0; i < compiledFunction->nLocals; ++i) - internalClass = internalClass->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); + for (quint32 i = 0; i < compiledFunction->nLocals; ++i) { + internalClass = internalClass->addMember( + engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), + Attr_NotConfigurable); + } Scope scope(engine); ScopedString arg(scope); diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 01b212370d..cbbb61c68c 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -51,7 +51,7 @@ // #include "qv4global_p.h" -#include +#include #include namespace JSC { @@ -65,9 +65,13 @@ struct QQmlSourceLocation; namespace QV4 { struct Q_QML_EXPORT FunctionData { - CompiledData::CompilationUnit *compilationUnit; + CompiledData::CompilationUnitBase *compilationUnit; - FunctionData(CompiledData::CompilationUnit *compilationUnit) + // Intentionally require an ExecutableCompilationUnit but save only a pointer to + // CompilationUnitBase. This is so that we can take advantage of the standard layout + // of CompilationUnitBase in the JIT. Furthermore we can safely static_cast to + // ExecutableCompilationUnit where we need it. + FunctionData(ExecutableCompilationUnit *compilationUnit) : compilationUnit(compilationUnit) {} }; @@ -76,12 +80,24 @@ Q_STATIC_ASSERT(std::is_standard_layout< FunctionData >::value); struct Q_QML_EXPORT Function : public FunctionData { private: - Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function); + Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit, + const CompiledData::Function *function); ~Function(); public: const CompiledData::Function *compiledFunction; + QV4::ExecutableCompilationUnit *executableCompilationUnit() const + { + // This is safe: We require an ExecutableCompilationUnit in the ctor. + return static_cast(compilationUnit); + } + + QV4::Heap::String *runtimeString(uint i) + { + return compilationUnit->runtimeStrings[i]; + } + ReturnedValue call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context); const char *codeData; @@ -96,7 +112,8 @@ public: int interpreterCallCount = 0; bool isEval = false; - static Function *create(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function); + static Function *create(ExecutionEngine *engine, ExecutableCompilationUnit *unit, + const CompiledData::Function *function); void destroy(); // used when dynamically assigning signal handlers (QQmlConnection) @@ -108,8 +125,8 @@ public: static QString prettyName(const Function *function, const void *address); - inline QString sourceFile() const { return compilationUnit->fileName(); } - inline QUrl finalUrl() const { return compilationUnit->finalUrl(); } + inline QString sourceFile() const { return executableCompilationUnit()->fileName(); } + inline QUrl finalUrl() const { return executableCompilationUnit()->finalUrl(); } inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; } inline bool isArrowFunction() const { return compiledFunction->flags & CompiledData::Function::IsArrowFunction; } @@ -121,7 +138,7 @@ public: { if (compiledFunction->nestedFunctionIndex == std::numeric_limits::max()) return nullptr; - return compilationUnit->runtimeFunctions[compiledFunction->nestedFunctionIndex]; + return executableCompilationUnit()->runtimeFunctions[compiledFunction->nestedFunctionIndex]; } }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 41a21ba379..b1b0d67e64 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -135,13 +135,13 @@ void Heap::FunctionObject::setFunction(Function *f) { if (f) { function = f; - function->compilationUnit->addref(); + function->executableCompilationUnit()->addref(); } } void Heap::FunctionObject::destroy() { if (function) - function->compilationUnit->release(); + function->executableCompilationUnit()->release(); Object::destroy(); } @@ -229,7 +229,7 @@ void Heap::FunctionCtor::init(QV4::ExecutionContext *scope) } // 15.3.2 -QQmlRefPointer FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t) +QQmlRefPointer FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t) { QString arguments; QString body; @@ -273,14 +273,15 @@ QQmlRefPointer FunctionCtor::parse(ExecutionEngin if (engine->hasException) return nullptr; - return cg.generateCompilationUnit(); + return ExecutableCompilationUnit::create(cg.generateCompilationUnit()); } ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) { ExecutionEngine *engine = f->engine(); - QQmlRefPointer compilationUnit = parse(engine, argv, argc, Type_Function); + QQmlRefPointer compilationUnit + = parse(engine, argv, argc, Type_Function); if (engine->hasException) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 4fee26f341..c99cad8e33 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -244,7 +244,7 @@ protected: Type_Function, Type_Generator }; - static QQmlRefPointer parse(ExecutionEngine *engine, const Value *argv, int argc, Type t = Type_Function); + static QQmlRefPointer parse(ExecutionEngine *engine, const Value *argv, int argc, Type t = Type_Function); }; struct FunctionPrototype: FunctionObject diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp index 14caa6953f..4eee6f4338 100644 --- a/src/qml/jsruntime/qv4generatorobject.cpp +++ b/src/qml/jsruntime/qv4generatorobject.cpp @@ -58,7 +58,7 @@ ReturnedValue GeneratorFunctionCtor::virtualCallAsConstructor(const FunctionObje { ExecutionEngine *engine = f->engine(); - QQmlRefPointer compilationUnit = parse(engine, argv, argc, Type_Generator); + QQmlRefPointer compilationUnit = parse(engine, argv, argc, Type_Generator); if (engine->hasException) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4module.cpp b/src/qml/jsruntime/qv4module.cpp index 237ada8321..08a1900383 100644 --- a/src/qml/jsruntime/qv4module.cpp +++ b/src/qml/jsruntime/qv4module.cpp @@ -52,7 +52,7 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(Module); -void Heap::Module::init(ExecutionEngine *engine, CompiledData::CompilationUnit *moduleUnit) +void Heap::Module::init(ExecutionEngine *engine, ExecutableCompilationUnit *moduleUnit) { Object::init(); @@ -106,7 +106,7 @@ void Module::evaluate() return; d()->evaluated = true; - CompiledData::CompilationUnit *unit = d()->unit; + ExecutableCompilationUnit *unit = d()->unit; unit->evaluateModuleRequests(); diff --git a/src/qml/jsruntime/qv4module_p.h b/src/qml/jsruntime/qv4module_p.h index dca0678fe9..aabb2e005e 100644 --- a/src/qml/jsruntime/qv4module_p.h +++ b/src/qml/jsruntime/qv4module_p.h @@ -60,7 +60,7 @@ namespace QV4 { namespace Heap { #define ModuleMembers(class, Member) \ - Member(class, NoMark, CompiledData::CompilationUnit *, unit) \ + Member(class, NoMark, ExecutableCompilationUnit *, unit) \ Member(class, Pointer, CallContext *, scope) \ Member(class, HeapValue, HeapValue, self) \ Member(class, NoMark, bool, evaluated) @@ -68,7 +68,7 @@ namespace Heap { DECLARE_EXPORTED_HEAP_OBJECT(Module, Object) { DECLARE_MARKOBJECTS(Module) - void init(ExecutionEngine *engine, CompiledData::CompilationUnit *moduleUnit); + void init(ExecutionEngine *engine, ExecutableCompilationUnit *moduleUnit); }; } diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index b337243204..26e1074fe3 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -49,7 +49,7 @@ namespace Profiling { FunctionLocation FunctionCall::resolveLocation() const { return FunctionLocation(m_function->name()->toQString(), - m_function->compilationUnit->fileName(), + m_function->executableCompilationUnit()->fileName(), m_function->compiledFunction->location.line, m_function->compiledFunction->location.column); } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index 8461384e9a..ccf7c9210d 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -144,19 +144,19 @@ public: FunctionCall(Function *function, qint64 start, qint64 end) : m_function(function), m_start(start), m_end(end) - { m_function->compilationUnit->addref(); } + { m_function->executableCompilationUnit()->addref(); } FunctionCall(const FunctionCall &other) : m_function(other.m_function), m_start(other.m_start), m_end(other.m_end) - { m_function->compilationUnit->addref(); } + { m_function->executableCompilationUnit()->addref(); } ~FunctionCall() - { m_function->compilationUnit->release(); } + { m_function->executableCompilationUnit()->release(); } FunctionCall &operator=(const FunctionCall &other) { if (&other != this) { - other.m_function->compilationUnit->addref(); - m_function->compilationUnit->release(); + other.m_function->executableCompilationUnit()->addref(); + m_function->executableCompilationUnit()->release(); m_function = other.m_function; m_start = other.m_start; m_end = other.m_end; @@ -189,22 +189,22 @@ public: SentMarker(const SentMarker &other) : m_function(other.m_function) { if (m_function) - m_function->compilationUnit->addref(); + m_function->executableCompilationUnit()->addref(); } ~SentMarker() { if (m_function) - m_function->compilationUnit->release(); + m_function->executableCompilationUnit()->release(); } SentMarker &operator=(const SentMarker &other) { if (&other != this) { if (m_function) - m_function->compilationUnit->release(); + m_function->executableCompilationUnit()->release(); m_function = other.m_function; - m_function->compilationUnit->addref(); + m_function->executableCompilationUnit()->addref(); } return *this; } @@ -213,7 +213,7 @@ public: { Q_ASSERT(m_function == nullptr); m_function = function; - m_function->compilationUnit->addref(); + m_function->executableCompilationUnit()->addref(); } bool isValid() const diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 107dfbda6f..478114a38a 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -224,6 +224,11 @@ void RuntimeCounters::count(const char *func, uint tag1, uint tag2) #ifndef V4_BOOTSTRAP +static QV4::Lookup *runtimeLookup(Function *f, uint i) +{ + return f->executableCompilationUnit()->runtimeLookups + i; +} + void RuntimeHelpers::numberToString(QString *result, double num, int radix) { Q_ASSERT(result); @@ -314,7 +319,8 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) ReturnedValue Runtime::Closure::call(ExecutionEngine *engine, int functionId) { - QV4::Function *clos = static_cast(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId]; + QV4::Function *clos = engine->currentStackFrame->v4Function->executableCompilationUnit() + ->runtimeFunctions[functionId]; Q_ASSERT(clos); ExecutionContext *current = static_cast(&engine->currentStackFrame->jsFrame->context); if (clos->isGenerator()) @@ -620,7 +626,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu ReturnedValue Runtime::GetTemplateObject::call(Function *function, int index) { - return function->compilationUnit->templateObjectAt(index)->asReturnedValue(); + return function->executableCompilationUnit()->templateObjectAt(index)->asReturnedValue(); } void Runtime::StoreProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) @@ -1077,33 +1083,33 @@ void Runtime::StoreSuperProperty::call(ExecutionEngine *engine, const Value &pro ReturnedValue Runtime::LoadGlobalLookup::call(ExecutionEngine *engine, Function *f, int index) { - Lookup *l = f->compilationUnit->runtimeLookups + index; + Lookup *l = runtimeLookup(f, index); return l->globalGetter(l, engine); } ReturnedValue Runtime::LoadQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index) { - Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index); return l->qmlContextPropertyGetter(l, engine, nullptr); } ReturnedValue Runtime::GetLookup::call(ExecutionEngine *engine, Function *f, const Value &base, int index) { - Lookup *l = f->compilationUnit->runtimeLookups + index; + Lookup *l = runtimeLookup(f, index); return l->getter(l, engine, base); } void Runtime::SetLookupSloppy::call(Function *f, const Value &base, int index, const Value &value) { ExecutionEngine *engine = f->internalClass->engine; - QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + QV4::Lookup *l = runtimeLookup(f, index); l->setter(l, engine, const_cast(base), value); } void Runtime::SetLookupStrict::call(Function *f, const Value &base, int index, const Value &value) { ExecutionEngine *engine = f->internalClass->engine; - QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + QV4::Lookup *l = runtimeLookup(f, index); if (!l->setter(l, engine, const_cast(base), value)) engine->throwTypeError(); } @@ -1366,12 +1372,13 @@ static ReturnedValue throwPropertyIsNotAFunctionTypeError(ExecutionEngine *engin ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint index, Value argv[], int argc) { Scope scope(engine); - Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index); Value function = Value::fromReturnedValue(l->globalGetter(l, engine)); Value thisObject = Value::undefinedValue(); - if (!function.isFunctionObject()) + if (!function.isFunctionObject()) { return throwPropertyIsNotAFunctionTypeError(engine, &thisObject, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); + } return static_cast(function).call(&thisObject, argv, argc); } @@ -1381,11 +1388,12 @@ ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engin { Scope scope(engine); ScopedValue thisObject(scope); - Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index); Value function = Value::fromReturnedValue(l->qmlContextPropertyGetter(l, engine, thisObject)); - if (!function.isFunctionObject()) + if (!function.isFunctionObject()) { return throwPropertyIsNotAFunctionTypeError(engine, thisObject, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); + } return static_cast(function).call(thisObject, argv, argc); } @@ -1420,9 +1428,11 @@ ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Va if (engine->hasException) return Encode::undefined(); - if (!f) - return throwPropertyIsNotAFunctionTypeError(engine, thisObject, - engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString()); + if (!f) { + return throwPropertyIsNotAFunctionTypeError( + engine, thisObject, engine->currentStackFrame->v4Function->compilationUnit + ->runtimeStrings[nameIndex]->toQString()); + } return f->call(thisObject, argv, argc); } @@ -1431,7 +1441,9 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value & { const Value *base = &baseRef; Scope scope(engine); - ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); + ScopedString name( + scope, + engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedObject lookupObject(scope, base); if (!lookupObject) { @@ -1469,7 +1481,7 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value & ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc) { - Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; + Lookup *l = runtimeLookup(engine->currentStackFrame->v4Function, index); // ok to have the value on the stack here Value f = Value::fromReturnedValue(l->getter(l, engine, base)); @@ -1789,7 +1801,8 @@ ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId, if (arg != ObjectLiteralArgument::Value) { Q_ASSERT(args[2].isInteger()); int functionId = args[2].integerValue(); - QV4::Function *clos = static_cast(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId]; + QV4::Function *clos = engine->currentStackFrame->v4Function->executableCompilationUnit() + ->runtimeFunctions[functionId]; Q_ASSERT(clos); PropertyKey::FunctionNamePrefix prefix = PropertyKey::None; @@ -1833,7 +1846,8 @@ ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId, ReturnedValue Runtime::CreateClass::call(ExecutionEngine *engine, int classIndex, const Value &superClass, Value computedNames[]) { - const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit; + const QV4::ExecutableCompilationUnit *unit + = engine->currentStackFrame->v4Function->executableCompilationUnit(); const QV4::CompiledData::Class *cls = unit->unitData()->classAt(classIndex); Scope scope(engine); diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 6cb2e95cdc..ee7f4dff0b 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -61,7 +61,7 @@ using namespace QV4; -Script::Script(ExecutionEngine *v4, QmlContext *qml, const QQmlRefPointer &compilationUnit) +Script::Script(ExecutionEngine *v4, QmlContext *qml, const QQmlRefPointer &compilationUnit) : line(1), column(0), context(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false) , compilationUnit(compilationUnit), vmFunction(nullptr), parseAsBinding(true) { @@ -133,7 +133,7 @@ void Script::parse() if (v4->hasException) return; - compilationUnit = cg.generateCompilationUnit(); + compilationUnit = QV4::ExecutableCompilationUnit::create(cg.generateCompilationUnit()); vmFunction = compilationUnit->linkToEngine(v4); } @@ -172,10 +172,11 @@ Function *Script::function() return vmFunction; } -QQmlRefPointer Script::precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator, - const QString &fileName, const QString &finalUrl, const QString &source, - QList *reportedErrors, - QV4::Compiler::ContextType contextType) +QV4::CompiledData::CompilationUnit Script::precompile( + QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, + Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, const QString &finalUrl, + const QString &source, QList *reportedErrors, + QV4::Compiler::ContextType contextType) { using namespace QV4::Compiler; using namespace QQmlJS::AST; @@ -219,8 +220,9 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo QQmlMetaType::CachedUnitLookupError cacheError = QQmlMetaType::CachedUnitLookupError::NoError; if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(originalUrl, &cacheError)) { - QQmlRefPointer jsUnit; - jsUnit.adopt(new QV4::CompiledData::CompilationUnit(cachedUnit)); + QQmlRefPointer jsUnit + = QV4::ExecutableCompilationUnit::create( + QV4::CompiledData::CompilationUnit(cachedUnit)); return new QV4::Script(engine, qmlContext, jsUnit); } diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index a1e9b83a8b..aecedea701 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -80,7 +80,7 @@ struct Q_QML_EXPORT Script { if (qml) qmlContext.set(engine, *qml); } - Script(ExecutionEngine *engine, QmlContext *qml, const QQmlRefPointer &compilationUnit); + Script(ExecutionEngine *engine, QmlContext *qml, const QQmlRefPointer &compilationUnit); ~Script(); QString sourceFile; int line; @@ -92,7 +92,7 @@ struct Q_QML_EXPORT Script { bool parsed; QV4::Compiler::ContextType contextType = QV4::Compiler::ContextType::Eval; QV4::PersistentValue qmlContext; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; Function *vmFunction; bool parseAsBinding; @@ -101,8 +101,10 @@ struct Q_QML_EXPORT Script { Function *function(); - static QQmlRefPointer precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator, - const QString &fileName, const QString &finalUrl, const QString &source, + static QV4::CompiledData::CompilationUnit precompile( + QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, + Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, + const QString &finalUrl, const QString &source, QList *reportedErrors = nullptr, QV4::Compiler::ContextType contextType = QV4::Compiler::ContextType::Global); static Script *createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl, QString *error); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index d348a79861..c6322fb504 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -565,14 +565,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(LoadGlobalLookup) STORE_IP(); - QV4::Lookup *l = function->compilationUnit->runtimeLookups + index; + QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index; acc = l->globalGetter(l, engine); CHECK_EXCEPTION; MOTH_END_INSTR(LoadGlobalLookup) MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup) STORE_IP(); - QV4::Lookup *l = function->compilationUnit->runtimeLookups + index; + QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index; acc = l->qmlContextPropertyGetter(l, engine, nullptr); CHECK_EXCEPTION; MOTH_END_INSTR(LoadQmlContextPropertyLookup) @@ -616,7 +616,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, STORE_IP(); STORE_ACC(); - QV4::Lookup *l = function->compilationUnit->runtimeLookups + index; + QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index; if (accumulator.isNullOrUndefined()) { QString message = QStringLiteral("Cannot read property '%1' of %2") @@ -640,7 +640,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(SetLookup) STORE_IP(); STORE_ACC(); - QV4::Lookup *l = function->compilationUnit->runtimeLookups + index; + QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index; if (!l->setter(l, engine, STACK_VALUE(base), accumulator) && function->isStrict()) engine->throwTypeError(); CHECK_EXCEPTION; @@ -722,7 +722,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(CallPropertyLookup) STORE_IP(); - Lookup *l = function->compilationUnit->runtimeLookups + lookupIndex; + Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex; if (stack[base].isNullOrUndefined()) { QString message = QStringLiteral("Cannot call method '%1' of %2") diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 656c7dd515..7fb15af570 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -335,7 +335,7 @@ protected: class QQmlTranslationBinding : public GenericBinding { public: - QQmlTranslationBinding(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) + QQmlTranslationBinding(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) { setCompilationUnit(compilationUnit); m_binding = binding; @@ -356,7 +356,7 @@ public: if (!isAddedToObject() || hasError()) return; - const QString result = m_binding->valueAsString(m_compilationUnit.data()); + const QString result = m_compilationUnit->bindingValueAsString(m_binding); Q_ASSERT(targetObject()); @@ -378,7 +378,7 @@ private: const QV4::CompiledData::Binding *m_binding; }; -QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt) +QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt) { QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding); diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index f192de4342..85b02dcde4 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -79,7 +79,7 @@ public: const QString &url = QString(), quint16 lineNumber = 0); static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function, QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope); - static QQmlBinding *createTranslationBinding(const QQmlRefPointer &unit, const QV4::CompiledData::Binding *binding, + static QQmlBinding *createTranslationBinding(const QQmlRefPointer &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt); ~QQmlBinding() override; diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index f9f26b6b1e..04debc0615 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -550,7 +550,8 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName, /*! \internal */ -QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::CompiledData::CompilationUnit *compilationUnit, int start, QObject *parent) +QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit, + int start, QObject *parent) : QQmlComponent(engine, parent) { Q_D(QQmlComponent); diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index 20199d0b21..39b6d4526f 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -59,9 +59,7 @@ class QQmlComponentPrivate; class QQmlComponentAttached; namespace QV4 { -namespace CompiledData { -struct CompilationUnit; -} +class ExecutableCompilationUnit; } class Q_QML_EXPORT QQmlComponent : public QObject @@ -128,7 +126,8 @@ protected: Q_INVOKABLE void incubateObject(QQmlV4Function *); private: - QQmlComponent(QQmlEngine *, QV4::CompiledData::CompilationUnit *compilationUnit, int, QObject *parent); + QQmlComponent(QQmlEngine *, QV4::ExecutableCompilationUnit *compilationUnit, int, + QObject *parent); Q_DISABLE_COPY(QQmlComponent) friend class QQmlTypeData; diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 4d9e4c6c15..71275a2cd3 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -105,7 +105,7 @@ public: qreal progress; int start; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; struct ConstructionState { ConstructionState() diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 3710cee162..e23f1e1e73 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -845,7 +845,7 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate() return QQmlContextPrivate::get(asQQmlContext()); } -void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer &unit, int subComponentIndex) +void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer &unit, int subComponentIndex) { typeCompilationUnit = unit; componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex; diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 7e3cef8e1d..1ddd04c9ff 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -66,7 +66,7 @@ #include #include -#include +#include #include QT_BEGIN_NAMESPACE @@ -152,12 +152,12 @@ public: QQmlIncubatorPrivate *incubator; // Compilation unit for contexts that belong to a compiled type. - QQmlRefPointer typeCompilationUnit; + QQmlRefPointer typeCompilationUnit; // object index in CompiledData::Unit to component that created this context int componentObjectIndex; - void initFromTypeCompilationUnit(const QQmlRefPointer &unit, int subComponentIndex); + void initFromTypeCompilationUnit(const QQmlRefPointer &unit, int subComponentIndex); // flag indicates whether the context owns the cache (after mutation) or not. mutable QV4::IdentifierHash propertyNameCache; diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index aa933553a8..c8e1300a1b 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -80,8 +80,8 @@ public: void clearErrors(); Flags flags() const { return m_flags; } - virtual void verifyBindings(const QQmlRefPointer &, const QList &) = 0; - virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &) = 0; + virtual void verifyBindings(const QQmlRefPointer &, const QList &) = 0; + virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &) = 0; QVector errors() const { return exceptions; } diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index f4c03fc17c..299476f5c8 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -76,8 +76,8 @@ class QQmlDataExtended; class QQmlNotifierEndpoint; namespace QV4 { +class ExecutableCompilationUnit; namespace CompiledData { -struct CompilationUnit; struct Binding; } } @@ -226,14 +226,14 @@ public: ~DeferredData(); unsigned int deferredIdx; QMultiHash bindings; - QQmlRefPointer compilationUnit;//Not always the same as the other compilation unit + QQmlRefPointer compilationUnit;//Not always the same as the other compilation unit QQmlContextData *context;//Could be either context or outerContext Q_DISABLE_COPY(DeferredData); }; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; QVector deferredData; - void deferData(int objectIndex, const QQmlRefPointer &, QQmlContextData *); + void deferData(int objectIndex, const QQmlRefPointer &, QQmlContextData *); void releaseDeferredData(); QV4::WeakValue jsWrapper; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index ea639d870b..8faace521a 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1770,7 +1770,7 @@ void QQmlData::NotifyList::layout() todo = nullptr; } -void QQmlData::deferData(int objectIndex, const QQmlRefPointer &compilationUnit, QQmlContextData *context) +void QQmlData::deferData(int objectIndex, const QQmlRefPointer &compilationUnit, QQmlContextData *context) { QQmlData::DeferredData *deferData = new QQmlData::DeferredData; deferData->deferredIdx = objectIndex; @@ -2407,7 +2407,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVe } } -void QQmlEnginePrivate::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) +void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) { compilationUnit->isRegisteredWithEngine = true; @@ -2417,7 +2417,7 @@ void QQmlEnginePrivate::registerInternalCompositeType(QV4::CompiledData::Compila m_compositeTypes.insert(compilationUnit->metaTypeId, compilationUnit); } -void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) +void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) { compilationUnit->isRegisteredWithEngine = false; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index ffe0e36d75..3b716683fd 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -219,8 +219,8 @@ public: QQmlMetaObject metaObjectForType(int) const; QQmlPropertyCache *propertyCacheForType(int); QQmlPropertyCache *rawPropertyCacheForType(int, int minorVersion = -1); - void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); - void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); + void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); + void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); bool isTypeLoaded(const QUrl &url) const; bool isScriptLoaded(const QUrl &url) const; @@ -265,7 +265,7 @@ private: // These members must be protected by a QQmlEnginePrivate::Locker as they are required by // the threaded loader. Only access them through their respective accessor methods. - QHash m_compositeTypes; + QHash m_compositeTypes; static bool s_designerMode; // These members is protected by the full QQmlEnginePrivate::mutex mutex diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h index 676ba1a29a..57ec8249cb 100644 --- a/src/qml/qml/qqmlincubator_p.h +++ b/src/qml/qml/qqmlincubator_p.h @@ -87,7 +87,7 @@ public: QPointer result; QQmlGuardedContextData rootContext; QQmlEnginePrivate *enginePriv; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; QScopedPointer creator; int subComponentToCreate; QQmlVMEGuard vmeGuard; diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 9a3a5218e0..e799267769 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -392,10 +392,10 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext, return; m_qmlScope.set(qmlContext->engine(), *qmlContext); m_v4Function = f; - setCompilationUnit(m_v4Function->compilationUnit); + setCompilationUnit(m_v4Function->executableCompilationUnit()); } -void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer &compilationUnit) +void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer &compilationUnit) { m_compilationUnit = compilationUnit; } diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 92f2ccbb4a..eecee08062 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -153,7 +153,7 @@ protected: void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line); void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f); - void setCompilationUnit(const QQmlRefPointer &compilationUnit); + void setCompilationUnit(const QQmlRefPointer &compilationUnit); // We store some flag bits in the following flag pointers. // activeGuards:flag1 - notifyOnValueChanged @@ -178,7 +178,7 @@ private: QQmlJavaScriptExpression *m_nextExpression; QV4::PersistentValue m_qmlScope; - QQmlRefPointer m_compilationUnit; + QQmlRefPointer m_compilationUnit; QV4::Function *m_v4Function; }; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 09df23de51..a5b92d14f7 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -499,7 +499,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit return QQmlType(priv); } -void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) +void QQmlMetaType::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) { QByteArray name = compilationUnit->rootPropertyCache()->className(); @@ -526,7 +526,7 @@ void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationU data->qmlLists.insert(lst_type, ptr_type); } -void QQmlMetaType::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) +void QQmlMetaType::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit) { int ptr_type = compilationUnit->metaTypeId; int lst_type = compilationUnit->listMetaTypeId; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 9af982d1c3..911e519cf2 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -61,6 +61,8 @@ class QQmlTypeModule; class QMutex; class QQmlError; +namespace QV4 { class ExecutableCompilationUnit; } + class Q_QML_PRIVATE_EXPORT QQmlMetaType { public: @@ -78,8 +80,8 @@ public: static void unregisterType(int type); - static void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); - static void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); + static void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); + static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); static void registerModule(const char *uri, int versionMajor, int versionMinor); static bool protectModule(const char *uri, int majVersion); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 18105aa75f..177c0d38bd 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -73,7 +73,7 @@ struct ActiveOCRestorer }; } -QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer &compilationUnit, QQmlContextData *creationContext, +QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator) : phase(Startup) , compilationUnit(compilationUnit) @@ -100,7 +100,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR } } -QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState) +QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState) : phase(Startup) , compilationUnit(compilationUnit) , propertyCaches(&compilationUnit->propertyCaches) @@ -373,7 +373,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const propertyType = QMetaType::Int; } else { // ### This should be resolved earlier at compile time and the binding value should be changed accordingly. - QVariant value = binding->valueAsString(compilationUnit.data()); + QVariant value = compilationUnit->bindingValueAsString(binding); bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context); Q_ASSERT(ok); Q_UNUSED(ok); @@ -438,7 +438,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const property->writeProperty(_qobject, &nullValue, propertyWriteFlags); } } else { - QString stringValue = binding->valueAsString(compilationUnit.data()); + QString stringValue = compilationUnit->bindingValueAsString(binding); if (property->isVarProperty()) { QV4::ScopedString s(scope, v4->newString(stringValue)); _vmeMetaObject->setVMEProperty(property->coreIndex(), s); @@ -451,25 +451,25 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const break; case QVariant::String: { assertOrNull(binding->evaluatesToString()); - QString value = binding->valueAsString(compilationUnit.data()); + QString value = compilationUnit->bindingValueAsString(binding); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::StringList: { assertOrNull(binding->evaluatesToString()); - QStringList value(binding->valueAsString(compilationUnit.data())); + QStringList value(compilationUnit->bindingValueAsString(binding)); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::ByteArray: { assertType(QV4::CompiledData::Binding::Type_String); - QByteArray value(binding->valueAsString(compilationUnit.data()).toUtf8()); + QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8()); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Url: { assertType(QV4::CompiledData::Binding::Type_String); - QString string = binding->valueAsString(compilationUnit.data()); + QString string = compilationUnit->bindingValueAsString(binding); // Encoded dir-separators defeat QUrl processing - decode them first string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive); QUrl value = string.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(string)); @@ -509,7 +509,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const break; case QVariant::Color: { bool ok = false; - uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(compilationUnit.data()), &ok); + uint colorValue = QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), &ok); assertOrNull(ok); struct { void *data[4]; } buffer; if (QQml_valueTypeProvider()->storeValueType(property->propType(), &colorValue, &buffer, sizeof(buffer))) { @@ -520,21 +520,21 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const #if QT_CONFIG(datestring) case QVariant::Date: { bool ok = false; - QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(compilationUnit.data()), &ok); + QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Time: { bool ok = false; - QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(compilationUnit.data()), &ok); + QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::DateTime: { bool ok = false; - QDateTime value = QQmlStringConverters::dateTimeFromString(binding->valueAsString(compilationUnit.data()), &ok); + QDateTime value = QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), &ok); // ### VME compatibility :( { const qint64 date = value.date().toJulianDay(); @@ -548,42 +548,42 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const #endif // datestring case QVariant::Point: { bool ok = false; - QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok).toPoint(); + QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint(); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::PointF: { bool ok = false; - QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Size: { bool ok = false; - QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok).toSize(); + QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize(); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::SizeF: { bool ok = false; - QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Rect: { bool ok = false; - QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok).toRect(); + QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect(); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::RectF: { bool ok = false; - QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok); + QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok); assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } @@ -599,7 +599,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float xp; float yp; } vec; - bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); + bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec)); assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); @@ -611,7 +611,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float yp; float zy; } vec; - bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); + bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec)); assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); @@ -624,7 +624,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float zy; float wp; } vec; - bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); + bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec)); assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); @@ -637,7 +637,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float yp; float zp; } vec; - bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); + bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec)); assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); @@ -669,7 +669,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const break; } else if (property->propType() == qMetaTypeId >()) { assertType(QV4::CompiledData::Binding::Type_String); - QString urlString = binding->valueAsString(compilationUnit.data()); + QString urlString = compilationUnit->bindingValueAsString(binding); QUrl u = urlString.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(urlString)); QList value; @@ -679,7 +679,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } else if (property->propType() == qMetaTypeId >()) { assertOrNull(binding->evaluatesToString()); QList value; - value.append(binding->valueAsString(compilationUnit.data())); + value.append(compilationUnit->bindingValueAsString(binding)); property->writeProperty(_qobject, &value, propertyWriteFlags); break; } else if (property->propType() == qMetaTypeId()) { @@ -695,14 +695,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { value = QJSValue::NullValue; } else { - value = QJSValue(binding->valueAsString(compilationUnit.data())); + value = QJSValue(compilationUnit->bindingValueAsString(binding)); } property->writeProperty(_qobject, &value, propertyWriteFlags); break; } // otherwise, try a custom type assignment - QString stringValue = binding->valueAsString(compilationUnit.data()); + QString stringValue = compilationUnit->bindingValueAsString(binding); QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType()); Q_ASSERT(converter); QVariant value = (*converter)(stringValue); @@ -816,7 +816,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper { if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty()); - QV4::CompiledData::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex); + QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex); Q_ASSERT(tr); QQmlType attachedType = tr->type; if (!attachedType.isValid()) { @@ -835,7 +835,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper // ### resolve this at compile time if (bindingProperty && bindingProperty->propType() == qMetaTypeId()) { - QQmlScriptString ss(binding->valueAsScriptString(compilationUnit.data()), context->asQQmlContext(), _scopeObject); + QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding), + context->asQQmlContext(), _scopeObject); ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid; ss.d.data()->lineNumber = binding->location.line; ss.d.data()->columnNumber = binding->location.column; @@ -1184,8 +1185,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo instance = component; ddata = QQmlData::get(instance, /*create*/true); } else { - QV4::CompiledData::ResolvedTypeReference *typeRef - = resolvedType(obj->inheritedTypeNameIndex); + QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); installPropertyCache = !typeRef->isFullyDynamicType; QQmlType type = typeRef->type; diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 5aca60e2f0..0766e2082e 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -85,7 +85,7 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator { Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator) public: - QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr); + QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr); ~QQmlObjectCreator(); QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr); @@ -104,7 +104,7 @@ public: QFiniteStack > &allCreatedObjects() const { return sharedState->allCreatedObjects; } private: - QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState); + QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState); void init(QQmlContextData *parentContext); @@ -125,7 +125,7 @@ private: inline QV4::QmlContext *currentQmlContext(); Q_NEVER_INLINE void createQmlContext(); - QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const + QV4::ResolvedTypeReference *resolvedType(int id) const { return compilationUnit->resolvedType(id); } @@ -141,7 +141,7 @@ private: QQmlEngine *engine; QV4::ExecutionEngine *v4; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; const QV4::CompiledData::Unit *qmlUnit; QQmlGuardedContextData parentContext; QQmlContextData *context; diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h index bafcba5971..285c34d7fa 100644 --- a/src/qml/qml/qqmlproperty_p.h +++ b/src/qml/qml/qqmlproperty_p.h @@ -59,6 +59,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 926e2810d5..6b4e0a0734 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -178,7 +178,7 @@ QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const QQmlRefPointer td(engine->typeLoader.getType(sourceUrl())); if (td.isNull() || !td->isComplete()) return QQmlType(); - QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit(); + QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit(); const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject(); return QQmlMetaType::qmlType(mo); } @@ -192,7 +192,7 @@ QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) c QQmlRefPointer td(engine->typeLoader.getType(sourceUrl())); if (td.isNull() || !td->isComplete()) return nullptr; - QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit(); + QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit(); return compilationUnit->rootPropertyCache().data(); } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 2233af6cd8..1022412292 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2136,7 +2136,7 @@ const QList &QQmlTypeData::resolvedScripts() cons return m_scripts; } -QV4::CompiledData::CompilationUnit *QQmlTypeData::compilationUnit() const +QV4::ExecutableCompilationUnit *QQmlTypeData::compilationUnit() const { return m_compiledData.data(); } @@ -2166,7 +2166,7 @@ bool QQmlTypeData::tryLoadFromDiskCache() if (!v4) return false; - QQmlRefPointer unit = QV4::Compiler::Codegen::createUnitForLoading(); + QQmlRefPointer unit = QV4::ExecutableCompilationUnit::create(); { QString error; if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) { @@ -2176,7 +2176,7 @@ bool QQmlTypeData::tryLoadFromDiskCache() } if (unit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation) { - restoreIR(unit); + restoreIR(std::move(*unit)); return true; } @@ -2232,8 +2232,9 @@ bool QQmlTypeData::tryLoadFromDiskCache() return true; } -void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer &typeNameCache, - const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) +void QQmlTypeData::createTypeAndPropertyCaches( + const QQmlRefPointer &typeNameCache, + const QV4::ResolvedTypeReferenceMap &resolvedTypeCache) { Q_ASSERT(m_compiledData); m_compiledData->typeNameCache = typeNameCache; @@ -2244,9 +2245,9 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer propertyCacheCreator(&m_compiledData->propertyCaches, - &pendingGroupPropertyBindings, - engine, m_compiledData.data(), &m_importCache); + QQmlPropertyCacheCreator propertyCacheCreator( + &m_compiledData->propertyCaches, &pendingGroupPropertyBindings, engine, + m_compiledData.data(), &m_importCache); QQmlCompileError error = propertyCacheCreator.buildMetaObjects(); if (error.isSet()) { setError(error); @@ -2254,7 +2255,8 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer aliasCreator(&m_compiledData->propertyCaches, m_compiledData.data()); + QQmlPropertyCacheAliasCreator aliasCreator( + &m_compiledData->propertyCaches, m_compiledData.data()); aliasCreator.appendAliasPropertiesToMetaObjects(); pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches); @@ -2346,7 +2348,7 @@ void QQmlTypeData::done() } QQmlRefPointer typeNameCache; - QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache; + QV4::ResolvedTypeReferenceMap resolvedTypeCache; { QQmlCompileError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); if (error.isSet()) { @@ -2509,7 +2511,7 @@ void QQmlTypeData::initializeFromCachedUnit(const QV4::CompiledData::Unit *unit) loader.load(); m_document->jsModule.fileName = urlString(); m_document->jsModule.finalUrl = finalUrlString(); - m_document->javaScriptCompilationUnit.adopt(new QV4::CompiledData::CompilationUnit(unit)); + m_document->javaScriptCompilationUnit = QV4::CompiledData::CompilationUnit(unit); continueLoadFromIR(); } @@ -2544,14 +2546,14 @@ bool QQmlTypeData::loadFromSource() return true; } -void QQmlTypeData::restoreIR(QQmlRefPointer unit) +void QQmlTypeData::restoreIR(QV4::CompiledData::CompilationUnit &&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 = unit; + m_document->javaScriptCompilationUnit = std::move(unit); continueLoadFromIR(); } @@ -2650,12 +2652,13 @@ QString QQmlTypeData::stringAt(int index) const } void QQmlTypeData::compile(const QQmlRefPointer &typeNameCache, - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) { Q_ASSERT(m_compiledData.isNull()); - const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit && m_document->javaScriptCompilationUnit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation; + const bool typeRecompilation = m_document && 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); @@ -2774,7 +2777,7 @@ void QQmlTypeData::resolveTypes() QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( QQmlRefPointer *typeNameCache, - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache + QV4::ResolvedTypeReferenceMap *resolvedTypeCache ) const { typeNameCache->adopt(new QQmlTypeNameCache(m_importCache)); @@ -2791,7 +2794,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine()); for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) { - QScopedPointer ref(new QV4::CompiledData::ResolvedTypeReference); + QScopedPointer ref(new QV4::ResolvedTypeReference); QQmlType qmlType = resolvedType->type; if (resolvedType->typeData) { if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) { @@ -3022,7 +3025,8 @@ QQmlRefPointer QQmlScriptBlob::scriptData() const void QQmlScriptBlob::dataReceived(const SourceCodeData &data) { if (!disableDiskCache() || forceDiskCache()) { - QQmlRefPointer unit = QV4::Compiler::Codegen::createUnitForLoading(); + QQmlRefPointer unit + = QV4::ExecutableCompilationUnit::create(); QString error; if (unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) { initializeFromCompilationUnit(unit); @@ -3047,7 +3051,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) return; } - QQmlRefPointer unit; + QV4::CompiledData::CompilationUnit unit; if (m_isModule) { QList diagnostics; @@ -3067,44 +3071,43 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) irUnit.jsParserEngine.setDirectives(&collector); QList errors; - unit = QV4::Script::precompile( - &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(), - source, &errors, QV4::Compiler::ContextType::ScriptImportedByQML); - // No need to addref on unit, it's initial refcount is 1 + irUnit.javaScriptCompilationUnit = QV4::Script::precompile( + &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(), + source, &errors, QV4::Compiler::ContextType::ScriptImportedByQML); + source.clear(); if (!errors.isEmpty()) { setError(errors); return; } - if (!unit) { - unit.adopt(new QV4::CompiledData::CompilationUnit); - } - irUnit.javaScriptCompilationUnit = unit; QmlIR::QmlUnitGenerator qmlGenerator; qmlGenerator.generate(irUnit); + unit = std::move(irUnit.javaScriptCompilationUnit); } + auto executableUnit = QV4::ExecutableCompilationUnit::create(std::move(unit)); + if ((!disableDiskCache() || forceDiskCache()) && !isDebugging()) { QString errorString; - if (unit->saveToDisk(url(), &errorString)) { + if (executableUnit->saveToDisk(url(), &errorString)) { QString error; - if (!unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) { + if (!executableUnit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) { // ignore error, keep using the in-memory compilation unit. } } else { - qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->fileName() << "to disk:" << errorString; + qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" + << executableUnit->fileName() << "to disk:" << errorString; } } - initializeFromCompilationUnit(unit); + initializeFromCompilationUnit(executableUnit); } void QQmlScriptBlob::initializeFromCachedUnit(const QV4::CompiledData::Unit *unit) { - QQmlRefPointer compilationUnit; - compilationUnit.adopt(new QV4::CompiledData::CompilationUnit(unit, urlString(), finalUrlString())); - initializeFromCompilationUnit(compilationUnit); + initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create( + QV4::CompiledData::CompilationUnit(unit, urlString(), finalUrlString()))); } void QQmlScriptBlob::done() @@ -3169,7 +3172,7 @@ void QQmlScriptBlob::scriptImported(const QQmlRefPointer &blob, m_scripts << ref; } -void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer &unit) +void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer &unit) { Q_ASSERT(!m_scriptData); m_scriptData.adopt(new QQmlScriptData()); @@ -3179,7 +3182,7 @@ void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer script = m_scriptData->m_precompiledScript; + QQmlRefPointer script = m_scriptData->m_precompiledScript; if (!m_isModule) { QList errors; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 987e47222d..d87812d48e 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -453,7 +454,7 @@ public: const QList &resolvedScripts() const; - QV4::CompiledData::CompilationUnit *compilationUnit() const; + QV4::ExecutableCompilationUnit *compilationUnit() const; // Used by QQmlComponent to get notifications struct TypeDataCallback { @@ -477,18 +478,18 @@ protected: private: bool tryLoadFromDiskCache(); bool loadFromSource(); - void restoreIR(QQmlRefPointer unit); + void restoreIR(QV4::CompiledData::CompilationUnit &&unit); void continueLoadFromIR(); void resolveTypes(); QQmlCompileError buildTypeResolutionCaches( QQmlRefPointer *typeNameCache, - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache + QV4::ResolvedTypeReferenceMap *resolvedTypeCache ) const; void compile(const QQmlRefPointer &typeNameCache, - QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, + QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); void createTypeAndPropertyCaches(const QQmlRefPointer &typeNameCache, - const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); + const QV4::ResolvedTypeReferenceMap &resolvedTypeCache); bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true, @@ -512,7 +513,7 @@ private: QMap m_resolvedTypes; bool m_typesResolved:1; - QQmlRefPointer m_compiledData; + QQmlRefPointer m_compiledData; QList m_callbacks; @@ -542,7 +543,7 @@ public: QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt); - QQmlRefPointer compilationUnit() const { return m_precompiledScript; } + QQmlRefPointer compilationUnit() const { return m_precompiledScript; } protected: void clear() override; // From QQmlCleanup @@ -554,7 +555,7 @@ private: QQmlContextData *qmlContextDataForContext(QQmlContextData *parentQmlContextData); bool m_loaded; - QQmlRefPointer m_precompiledScript; + QQmlRefPointer m_precompiledScript; QV4::PersistentValue m_value; }; @@ -587,7 +588,7 @@ protected: private: void scriptImported(const QQmlRefPointer &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override; - void initializeFromCompilationUnit(const QQmlRefPointer &unit); + void initializeFromCompilationUnit(const QQmlRefPointer &unit); QList m_scripts; QQmlRefPointer m_scriptData; diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 236daac75c..9db089c330 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -418,7 +418,7 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const return Encode(false); QQmlRefPointer td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); - CompiledData::CompilationUnit *cu = td->compilationUnit(); + ExecutableCompilationUnit *cu = td->compilationUnit(); myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); } else { myQmlType = qenginepriv->metaObjectForType(myTypeId); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 5d13415513..2881e71805 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -316,7 +316,7 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, - const QQmlRefPointer &cache, const QQmlRefPointer &qmlCompilationUnit, int qmlObjectId) + const QQmlRefPointer &cache, const QQmlRefPointer &qmlCompilationUnit, int qmlObjectId) : QQmlInterceptorMetaObject(obj, cache), engine(engine), ctxt(QQmlData::get(obj, true)->outerContext), diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 2371d70f10..5025987586 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -144,7 +144,7 @@ class QQmlVMEMetaObjectEndpoint; class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject { public: - QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer &cache, const QQmlRefPointer &qmlCompilationUnit, int qmlObjectId); + QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer &cache, const QQmlRefPointer &qmlCompilationUnit, int qmlObjectId); ~QQmlVMEMetaObject() override; bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const; @@ -226,7 +226,7 @@ public: // keep a reference to the compilation unit in order to still // do property access when the context has been invalidated. - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; const QV4::CompiledData::Object *compiledObject; }; diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 532bfa8754..4838ef3814 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1950,7 +1950,8 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value CppStackFrame *frame = scope.engine->currentStackFrame; // The first non-empty source URL in the call stack determines the translation context. while (frame && context.isEmpty()) { - if (CompiledData::CompilationUnit *unit = frame->v4Function->compilationUnit) { + if (CompiledData::CompilationUnitBase *baseUnit = frame->v4Function->compilationUnit) { + const auto *unit = static_cast(baseUnit); QString fileName = unit->fileName(); QUrl url(unit->fileName()); if (url.isValid() && url.isRelative()) { diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index f601087690..8ec754a9df 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -66,7 +66,7 @@ public: bool ignoreUnknownSignals; bool componentcomplete; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; QList bindings; }; @@ -231,7 +231,7 @@ void QQmlConnections::setIgnoreUnknownSignals(bool ignore) d->ignoreUnknownSignals = ignore; } -void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) +void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) { for (int ii = 0; ii < props.count(); ++ii) { const QV4::CompiledData::Binding *binding = props.at(ii); @@ -256,7 +256,7 @@ void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) +void QQmlConnectionsParser::applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) { QQmlConnectionsPrivate *p = static_cast(QObjectPrivate::get(object)); diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h index bd03d7e152..f6ad1eb46c 100644 --- a/src/qml/types/qqmlconnections_p.h +++ b/src/qml/types/qqmlconnections_p.h @@ -98,8 +98,8 @@ private: class QQmlConnectionsParser : public QQmlCustomParser { public: - void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; - void applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) override; + void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; + void applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) override; }; diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index 5b5bcd8464..d1219d958a 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -314,7 +314,7 @@ QString StringOrTranslation::toString(const QQmlListModel *owner) const } if (!owner) return QString(); - return d.asT2()->valueAsString(owner->m_compilationUnit.data()); + return owner->m_compilationUnit->bindingValueAsString(d.asT2()); } QString StringOrTranslation::asString() const @@ -2676,7 +2676,7 @@ void QQmlListModel::sync() qmlWarning(this) << "List sync() can only be called from a WorkerScript"; } -bool QQmlListModelParser::verifyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) +bool QQmlListModelParser::verifyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) { if (binding->type >= QV4::CompiledData::Binding::Type_Object) { const quint32 targetObjectIndex = binding->value.objectIndex; @@ -2707,7 +2707,7 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointertype == QV4::CompiledData::Binding::Type_Script) { - QString scriptStr = binding->valueAsScriptString(compilationUnit.data()); + QString scriptStr = compilationUnit->bindingValueAsScriptString(binding); if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) { QByteArray script = scriptStr.toUtf8(); bool ok; @@ -2722,7 +2722,9 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex) +bool QQmlListModelParser::applyProperty( + const QQmlRefPointer &compilationUnit, + const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex) { const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex); @@ -2759,7 +2761,7 @@ bool QQmlListModelParser::applyProperty(const QQmlRefPointerisTranslationBinding()) { value = QVariant::fromValue(binding); } else if (binding->evaluatesToString()) { - value = binding->valueAsString(compilationUnit.data()); + value = compilationUnit->bindingValueAsString(binding); } else if (binding->type == QV4::CompiledData::Binding::Type_Number) { value = binding->valueAsNumber(compilationUnit->constants); } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) { @@ -2767,7 +2769,7 @@ bool QQmlListModelParser::applyProperty(const QQmlRefPointertype == QV4::CompiledData::Binding::Type_Null) { value = QVariant::fromValue(nullptr); } else if (binding->type == QV4::CompiledData::Binding::Type_Script) { - QString scriptStr = binding->valueAsScriptString(compilationUnit.data()); + QString scriptStr = compilationUnit->bindingValueAsScriptString(binding); if (definesEmptyList(scriptStr)) { const ListLayout::Role &role = model->getOrCreateListRole(elementName); ListModel *emptyModel = new ListModel(role.subLayout, nullptr); @@ -2802,7 +2804,7 @@ bool QQmlListModelParser::applyProperty(const QQmlRefPointer &compilationUnit, const QList &bindings) +void QQmlListModelParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) { listElementTypeName = QString(); // unknown @@ -2817,7 +2819,7 @@ void QQmlListModelParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) +void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) { QQmlListModel *rv = static_cast(obj); diff --git a/src/qmlmodels/qqmllistmodel_p.h b/src/qmlmodels/qqmllistmodel_p.h index 4aabd790a5..10d67c1c6f 100644 --- a/src/qmlmodels/qqmllistmodel_p.h +++ b/src/qmlmodels/qqmllistmodel_p.h @@ -137,7 +137,7 @@ private: mutable QQmlListModelWorkerAgent *m_agent; mutable QV4::ExecutionEngine *m_engine; - QQmlRefPointer m_compilationUnit; + QQmlRefPointer m_compilationUnit; bool m_mainThread; bool m_primary; @@ -188,13 +188,13 @@ public: QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {} - void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) override; - void applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) override; + void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) override; + void applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) override; private: - bool verifyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding); + bool verifyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding); // returns true if a role was set - bool applyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex); + bool applyProperty(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex); static bool definesEmptyList(const QString &); diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 9cddf61543..6aff7af0e7 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -70,6 +70,7 @@ #include #include +#include #ifdef QT_QMLTEST_WITH_WIDGETS #include @@ -290,7 +291,8 @@ public: m_errors += component.errors(); if (component.isReady()) { - QQmlRefPointer rootCompilationUnit = QQmlComponentPrivate::get(&component)->compilationUnit; + QQmlRefPointer rootCompilationUnit + = QQmlComponentPrivate::get(&component)->compilationUnit; TestCaseEnumerationResult result = enumerateTestCases(rootCompilationUnit.data()); m_testCases = result.testCases + result.finalizedPartialTestCases(); m_errors += result.errors; @@ -330,7 +332,8 @@ private: } }; - TestCaseEnumerationResult enumerateTestCases(CompilationUnit *compilationUnit, const Object *object = nullptr) + TestCaseEnumerationResult enumerateTestCases(QV4::ExecutableCompilationUnit *compilationUnit, + const Object *object = nullptr) { QQmlType testCaseType; for (quint32 i = 0, count = compilationUnit->importCount(); i < count; ++i) { @@ -353,7 +356,9 @@ private: if (!object) // Start at root of compilation unit if not enumerating a specific child object = compilationUnit->objectAt(0); - if (CompilationUnit *superTypeUnit = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex)->compilationUnit.data()) { + if (QV4::ExecutableCompilationUnit *superTypeUnit + = compilationUnit->resolvedTypes.value(object->inheritedTypeNameIndex) + ->compilationUnit.data()) { // We have a non-C++ super type, which could indicate we're a subtype of a TestCase if (testCaseType.isValid() && superTypeUnit->url() == testCaseType.sourceUrl()) result.isTestCase = true; diff --git a/src/quick/designer/qquickdesignercustomparserobject.cpp b/src/quick/designer/qquickdesignercustomparserobject.cpp index 50a8b6a25b..841aae5bc3 100644 --- a/src/quick/designer/qquickdesignercustomparserobject.cpp +++ b/src/quick/designer/qquickdesignercustomparserobject.cpp @@ -46,12 +46,12 @@ QQuickDesignerCustomParserObject::QQuickDesignerCustomParserObject() } -void QQuickDesignerCustomParser::verifyBindings(const QQmlRefPointer &, const QList &) +void QQuickDesignerCustomParser::verifyBindings(const QQmlRefPointer &, const QList &) { /* Nothing to do we accept anything */ } -void QQuickDesignerCustomParser::applyBindings(QObject *, const QQmlRefPointer &, const QList &) +void QQuickDesignerCustomParser::applyBindings(QObject *, const QQmlRefPointer &, const QList &) { /* Nothing to do we accept anything */ } diff --git a/src/quick/designer/qquickdesignercustomparserobject_p.h b/src/quick/designer/qquickdesignercustomparserobject_p.h index b38417d102..4da00ea841 100644 --- a/src/quick/designer/qquickdesignercustomparserobject_p.h +++ b/src/quick/designer/qquickdesignercustomparserobject_p.h @@ -70,8 +70,8 @@ public: QQuickDesignerCustomParser() : QQmlCustomParser(AcceptsAttachedProperties | AcceptsSignalHandlers) {} - void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; - void applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) override; + void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; + void applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) override; }; QT_END_NAMESPACE diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index d739c8a017..6aec1219ef 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -201,14 +201,14 @@ public: QPointer object; QList bindings; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; bool decoded : 1; bool restore : 1; bool isExplicit : 1; void decode(); - void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer &qmlUnit, const QV4::CompiledData::Binding *binding); + void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer &qmlUnit, const QV4::CompiledData::Binding *binding); class ExpressionChange { public: @@ -236,7 +236,7 @@ public: QQmlProperty property(const QString &); }; -void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) +void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) { if (binding->type == QV4::CompiledData::Binding::Type_Object) { error(compilationUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects.")); @@ -266,7 +266,7 @@ void QQuickPropertyChangesPrivate::decode() decoded = true; } -void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) +void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding) { Q_Q(QQuickPropertyChanges); @@ -314,7 +314,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, QQmlBinding::Identifier id = QQmlBinding::Invalid; if (!binding->isTranslationBinding()) { - expression = binding->valueAsString(compilationUnit.data()); + expression = compilationUnit->bindingValueAsString(binding); id = binding->value.compiledScriptIndex; } expressions << ExpressionChange(propertyName, binding, id, expression, url, line, column); @@ -328,7 +328,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, case QV4::CompiledData::Binding::Type_TranslationById: Q_UNREACHABLE(); case QV4::CompiledData::Binding::Type_String: - var = binding->valueAsString(compilationUnit.data()); + var = compilationUnit->bindingValueAsString(binding); break; case QV4::CompiledData::Binding::Type_Number: var = binding->valueAsNumber(compilationUnit->constants); @@ -346,13 +346,13 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, properties << qMakePair(propertyName, var); } -void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) +void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) { for (int ii = 0; ii < props.count(); ++ii) verifyList(compilationUnit, props.at(ii)); } -void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) +void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) { QQuickPropertyChangesPrivate *p = static_cast(QObjectPrivate::get(obj)); diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h index 74fe511d6e..82a6ebffac 100644 --- a/src/quick/util/qquickpropertychanges_p.h +++ b/src/quick/util/qquickpropertychanges_p.h @@ -101,10 +101,10 @@ public: QQuickPropertyChangesParser() : QQmlCustomParser(AcceptsAttachedProperties) {} - void verifyList(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding); + void verifyList(const QQmlRefPointer &compilationUnit, const QV4::CompiledData::Binding *binding); - void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; - void applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) override; + void verifyBindings(const QQmlRefPointer &compilationUnit, const QList &props) override; + void applyBindings(QObject *obj, const QQmlRefPointer &compilationUnit, const QList &bindings) override; }; diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp index cbe3be2e70..33efcb4da4 100644 --- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp +++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp @@ -509,7 +509,7 @@ static bool executeTest(const QByteArray &data, bool runAsModule = false, const QVector modulesToLoad = { rootModuleUrl }; while (!modulesToLoad.isEmpty()) { QUrl url = modulesToLoad.takeFirst(); - QQmlRefPointer module; + QQmlRefPointer module; QFile f(url.toLocalFile()); if (f.open(QIODevice::ReadOnly)) { diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index e86b7bf5fe..2987e420fe 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -118,7 +119,8 @@ struct TestCompiler { closeMapping(); testFilePath = baseDirectory + QStringLiteral("/test.qml"); - cacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath)); + cacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath( + QUrl::fromLocalFile(testFilePath)); mappedFile.setFileName(cacheFilePath); } @@ -185,8 +187,10 @@ struct TestCompiler bool verify() { - QQmlRefPointer unit = QV4::Compiler::Codegen::createUnitForLoading(); - return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), QFileInfo(testFilePath).lastModified(), &lastErrorString); + QQmlRefPointer unit + = QV4::ExecutableCompilationUnit::create(); + return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), + QFileInfo(testFilePath).lastModified(), &lastErrorString); } void closeMapping() @@ -263,8 +267,9 @@ void tst_qmldiskcache::loadLocalAsFallback() f.write(reinterpret_cast(&unit), sizeof(unit)); } - QQmlRefPointer unit = QV4::Compiler::Codegen::createUnitForLoading(); - bool loaded = unit->loadFromDisk(QUrl::fromLocalFile(testCompiler.testFilePath), QFileInfo(testCompiler.testFilePath).lastModified(), + QQmlRefPointer unit = QV4::ExecutableCompilationUnit::create(); + bool loaded = unit->loadFromDisk(QUrl::fromLocalFile(testCompiler.testFilePath), + QFileInfo(testCompiler.testFilePath).lastModified(), &testCompiler.lastErrorString); QVERIFY2(loaded, qPrintable(testCompiler.lastErrorString)); QCOMPARE(unit->objectCount(), 1); @@ -572,7 +577,8 @@ void tst_qmldiskcache::fileSelectors() QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 42); - QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath))); + QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath( + QUrl::fromLocalFile(testFilePath))); QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName())); } @@ -587,7 +593,8 @@ void tst_qmldiskcache::fileSelectors() QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 100); - QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(selectedTestFilePath))); + QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath( + QUrl::fromLocalFile(selectedTestFilePath))); QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName())); } } @@ -737,7 +744,8 @@ void tst_qmldiskcache::stableOrderOfDependentCompositeTypes() QVERIFY2(firstDependentTypeClassName.contains("QMLTYPE"), firstDependentTypeClassName.constData()); QVERIFY2(secondDependentTypeClassName.contains("QMLTYPE"), secondDependentTypeClassName.constData()); - const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath)); + const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath( + QUrl::fromLocalFile(testFilePath)); QVERIFY(QFile::exists(testFileCachePath)); QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); @@ -815,7 +823,8 @@ void tst_qmldiskcache::singletonDependency() QCOMPARE(obj->property("value").toInt(), 42); } - const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath)); + const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath( + QUrl::fromLocalFile(testFilePath)); QVERIFY(QFile::exists(testFileCachePath)); QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); @@ -872,7 +881,8 @@ void tst_qmldiskcache::cppRegisteredSingletonDependency() QCOMPARE(value.toInt(), 42); } - const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(QUrl::fromLocalFile(testFilePath)); + const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath( + QUrl::fromLocalFile(testFilePath)); QVERIFY(QFile::exists(testFileCachePath)); QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index f9a6ee8e5a..d6215307bf 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -125,7 +125,7 @@ QVariant myCustomVariantTypeConverter(const QString &data) } -void CustomBindingParser::applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) +void CustomBindingParser::applyBindings(QObject *object, const QQmlRefPointer &compilationUnit, const QList &bindings) { CustomBinding *customBinding = qobject_cast(object); Q_ASSERT(customBinding); @@ -154,7 +154,7 @@ void CustomBinding::componentComplete() } } -void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) +void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer &compilationUnit, const QList &bindings) { if (bindings.count() != 1) { error(bindings.first(), QStringLiteral("Custom parser invoked incorrectly for unit test")); @@ -184,7 +184,7 @@ void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer &, const QList &bindings) +void SimpleObjectCustomParser::applyBindings(QObject *object, const QQmlRefPointer &, const QList &bindings) { SimpleObjectWithCustomParser *o = qobject_cast(object); Q_ASSERT(o); diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index bb6e9582c2..0618d2b20f 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -781,15 +781,15 @@ class MyCustomParserType : public QObject class MyCustomParserTypeParser : public QQmlCustomParser { public: - virtual void verifyBindings(const QQmlRefPointer &, const QList &) {} - virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &) {} + virtual void verifyBindings(const QQmlRefPointer &, const QList &) {} + virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &) {} }; class EnumSupportingCustomParser : public QQmlCustomParser { public: - virtual void verifyBindings(const QQmlRefPointer &, const QList &); - virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &) {} + virtual void verifyBindings(const QQmlRefPointer &, const QList &); + virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &) {} }; class MyParserStatus : public QObject, public QQmlParserStatus @@ -1275,15 +1275,15 @@ public: void setTarget(QObject *newTarget) { m_target = newTarget; } QPointer m_target; - QQmlRefPointer compilationUnit; + QQmlRefPointer compilationUnit; QList bindings; QByteArray m_bindingData; }; class CustomBindingParser : public QQmlCustomParser { - virtual void verifyBindings(const QQmlRefPointer &, const QList &) {} - virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &); + virtual void verifyBindings(const QQmlRefPointer &, const QList &) {} + virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &); }; class SimpleObjectWithCustomParser : public QObject @@ -1328,8 +1328,8 @@ private: class SimpleObjectCustomParser : public QQmlCustomParser { - virtual void verifyBindings(const QQmlRefPointer &, const QList &) {} - virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &); + virtual void verifyBindings(const QQmlRefPointer &, const QList &) {} + virtual void applyBindings(QObject *, const QQmlRefPointer &, const QList &); }; class RootObjectInCreationTester : public QObject diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 08dab99e0f..8cbb39974e 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -2225,7 +2225,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode() QV4::CompiledData::Unit *qmlUnit = reinterpret_cast(malloc(readOnlyQmlUnit->unitSize)); memcpy(qmlUnit, readOnlyQmlUnit, readOnlyQmlUnit->unitSize); qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData; - QQmlRefPointer compilationUnit = td->compilationUnit(); + QQmlRefPointer compilationUnit = td->compilationUnit(); compilationUnit->setUnitData(qmlUnit); const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0); @@ -2235,9 +2235,9 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode() const QV4::CompiledData::Binding *binding = rootObject->bindingTable() + i; if (compilationUnit->stringAt(binding->propertyNameIndex) != QString("scriptProperty")) continue; - QCOMPARE(binding->valueAsScriptString(compilationUnit.data()), QString("intProperty")); + QCOMPARE(compilationUnit->bindingValueAsScriptString(binding), QString("intProperty")); const_cast(binding)->stringIndex = 0; // empty string index - QVERIFY(binding->valueAsScriptString(compilationUnit.data()).isEmpty()); + QVERIFY(compilationUnit->bindingValueAsScriptString(binding).isEmpty()); break; } QVERIFY(i < rootObject->nBindings); diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp index 809a9bd9db..3b17df9872 100644 --- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp +++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp @@ -85,7 +85,8 @@ void tst_qqmltranslation::translation() << QStringLiteral("disambiguation") << QStringLiteral("singular") << QStringLiteral("plural"); - const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0); + const QV4::CompiledData::Object *rootObject + = 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); @@ -139,7 +140,8 @@ void tst_qqmltranslation::idTranslation() QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit(); QVERIFY(compilationUnit); - const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0); + const QV4::CompiledData::Object *rootObject + = 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/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index bf0bcaf04e..63be5c5ec4 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -169,7 +169,7 @@ static bool checkArgumentsObjectUseInSignalHandlers(const QmlIR::Document &doc, return true; } -using SaveFunction = std::function &, QString *)>; +using SaveFunction = std::function; static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFunction, Error *error) { @@ -229,7 +229,7 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti QmlIR::QmlUnitGenerator generator; irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false); generator.generate(irDocument); - QV4::CompiledData::Unit *unit = const_cast(irDocument.javaScriptCompilationUnit->data); + QV4::CompiledData::Unit *unit = const_cast(irDocument.javaScriptCompilationUnit.data); unit->flags |= QV4::CompiledData::Unit::StaticData; unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation; @@ -241,7 +241,7 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti static bool compileJSFile(const QString &inputFileName, const QString &inputFileUrl, SaveFunction saveFunction, Error *error) { - QQmlRefPointer unit; + QV4::CompiledData::CompilationUnit unit; QString sourceCode; { @@ -265,7 +265,7 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile unit = QV4::Compiler::Codegen::compileModule(/*debugMode*/false, url, sourceCode, QDateTime(), &diagnostics); error->appendDiagnostics(inputFileName, diagnostics); - if (!unit) + if (!unit.unitData()) return false; } else { QmlIR::Document irDocument(/*debugMode*/false); @@ -321,9 +321,9 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false); QmlIR::QmlUnitGenerator generator; generator.generate(irDocument); - QV4::CompiledData::Unit *unitData = const_cast(irDocument.javaScriptCompilationUnit->data); + QV4::CompiledData::Unit *unitData = const_cast(irDocument.javaScriptCompilationUnit.data); unitData->flags |= QV4::CompiledData::Unit::StaticData; - unit = irDocument.javaScriptCompilationUnit; + unit = std::move(irDocument.javaScriptCompilationUnit); } } @@ -331,7 +331,8 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile } static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFileName, - const QQmlRefPointer &unit, QString *errorString) + const QV4::CompiledData::CompilationUnit &unit, + QString *errorString) { QSaveFile f(outputFileName); if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { @@ -368,8 +369,8 @@ static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFil QByteArray hexifiedData; { QByteArray modifiedUnit; - modifiedUnit.resize(unit->data->unitSize); - memcpy(modifiedUnit.data(), unit->data, unit->data->unitSize); + modifiedUnit.resize(unit.data->unitSize); + memcpy(modifiedUnit.data(), unit.data, unit.data->unitSize); const char *dataPtr = modifiedUnit.data(); QV4::CompiledData::Unit *unitPtr; memcpy(&unitPtr, &dataPtr, sizeof(unitPtr)); @@ -377,7 +378,7 @@ static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFil QTextStream stream(&hexifiedData); const uchar *begin = reinterpret_cast(modifiedUnit.constData()); - const uchar *end = begin + unit->data->unitSize; + const uchar *end = begin + unit.data->unitSize; stream << hex; int col = 0; for (const uchar *data = begin; data < end; ++data, ++col) { @@ -525,13 +526,16 @@ int main(int argc, char **argv) inputFileUrl = QStringLiteral("qrc://") + inputResourcePath; - saveFunction = [inputResourcePath, outputFileName](const QQmlRefPointer &unit, QString *errorString) { + saveFunction = [inputResourcePath, outputFileName]( + const QV4::CompiledData::CompilationUnit &unit, + QString *errorString) { return saveUnitAsCpp(inputResourcePath, outputFileName, unit, errorString); }; } else { - saveFunction = [outputFileName](const QQmlRefPointer &unit, QString *errorString) { - return unit->saveToDisk(outputFileName, errorString); + saveFunction = [outputFileName](const QV4::CompiledData::CompilationUnit &unit, + QString *errorString) { + return unit.saveToDisk(outputFileName, errorString); }; } diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp index 4b581fff05..ba5e5f553c 100644 --- a/tools/qmljs/qmljs.cpp +++ b/tools/qmljs/qmljs.cpp @@ -137,7 +137,8 @@ int main(int argc, char *argv[]) } QScopedPointer script; if (cache && QFile::exists(fn + QLatin1Char('c'))) { - QQmlRefPointer unit = QV4::Compiler::Codegen::createUnitForLoading(); + QQmlRefPointer unit + = QV4::ExecutableCompilationUnit::create(); QString error; if (unit->loadFromDisk(QUrl::fromLocalFile(fn), QFileInfo(fn).lastModified(), &error)) { script.reset(new QV4::Script(&vm, nullptr, unit)); -- cgit v1.2.3