From 56f29d005c2c6eb028e3ed2d1ef8edd6d03d1403 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 12 Jun 2017 10:27:54 +0200 Subject: Pass the JSUnitGenerator into the codegen Allow registering all the required data to generate the proper compilationunit already in the codegenerator. Change-Id: I36345cc01927b3f8dc3ba6d91da175bd6abe124a Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index c09fde86f1..ed7a2774ea 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -140,7 +140,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() sss.scan(); } - QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); + QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; -- cgit v1.2.3 From 52e3a59b1de607636926822f1016f0e264bc4ad3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 21 Jun 2017 14:17:04 +0200 Subject: Re-enable lookups Change-Id: I02d57d2cbb4ae56c0c4626d96cbdf9935b366579 Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index ed7a2774ea..18a1cbdc93 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -141,6 +141,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() } QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); + v4CodeGenerator.setUseFastLookups(false); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; -- cgit v1.2.3 From 40e8109ceff8519920245a01d82357dc57639f46 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Jun 2017 09:44:55 +0200 Subject: Don't use the ISel's anymore Move the code that generates the CompilationUnit over to Codegen, and don't use the ISel's at all anymore when compiling JS/QML. Change-Id: Iba89082c386c3d3fd58ac25a4651c5d39178cc5c Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 18a1cbdc93..63a240e575 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -142,6 +142,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); v4CodeGenerator.setUseFastLookups(false); + // ### v4CodeGenerator.setUseTypeInference(true); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; @@ -149,11 +150,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() QQmlJavaScriptBindingExpressionSimplificationPass pass(document->objects, &document->jsModule, &document->jsGenerator); pass.reduceTranslationBindings(); - QV4::ExecutionEngine *v4 = engine->v4engine(); - QScopedPointer isel(v4->iselFactory->create(engine, v4->executableAllocator, &document->jsModule, &document->jsGenerator)); - isel->setUseFastLookups(false); - isel->setUseTypeInference(true); - document->javaScriptCompilationUnit = isel->compile(/*generated unit data*/false); + document->javaScriptCompilationUnit = v4CodeGenerator.generateCompilationUnit(/*generated unit data*/false); } // Generate QML compiled type data structures -- cgit v1.2.3 From 14a20fb683b0473909e5e206ac82dc7a18d40060 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Jun 2017 10:01:04 +0200 Subject: Remove the old compiler pipeline Don't compile the JIT and related code into libQtQml anymore. Change-Id: Ieb0ec33c964d09b121ede4097fe4218b147c673d Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 63a240e575..e98f380945 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include "qqmlpropertycachecreator_p.h" #include "qv4jssimplifier_p.h" -- cgit v1.2.3 From e049377f366dad8f42a3a632be5b347b7f7b4af2 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Jun 2017 13:35:59 +0200 Subject: Fix bugs in qqmlirbuilder Correctly add the scope and context object dependencies, and pass the correct index into LoadIdObject. Change-Id: Idc0d5b229fca40dad6a0ecd4988b4f150db4c0a2 Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index e98f380945..035414c114 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -146,8 +146,10 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() if (!jsCodeGen.generateCodeForComponents()) return nullptr; +#if 0 // ### QQmlJavaScriptBindingExpressionSimplificationPass pass(document->objects, &document->jsModule, &document->jsGenerator); pass.reduceTranslationBindings(); +#endif document->javaScriptCompilationUnit = v4CodeGenerator.generateCompilationUnit(/*generated unit data*/false); } -- cgit v1.2.3 From 30a50e5387839c30a381992ded185a862858f791 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 29 Jun 2017 16:23:40 +0200 Subject: Smaller cleanup Get rid of the filename argument for JSCodeGen. Change-Id: I4510a36374f8e98ac1d77edb2391d2413def3a46 Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 035414c114..1f459f1d13 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -139,7 +139,8 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() sss.scan(); } - QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); + document->jsModule.setFileName(typeData->finalUrlString()); + QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); v4CodeGenerator.setUseFastLookups(false); // ### v4CodeGenerator.setUseTypeInference(true); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); -- cgit v1.2.3 From 3a9f4d3ae701c7119016a0bf8b4e65ceb17864b0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 30 Jun 2017 08:44:09 +0200 Subject: Get rid of IR::Module and IR::Function Fold the stuff from IR::Function into QQmlJS::Context, and add a QQmlJS::Module class to replace the last pieces of the old IR. Change-Id: Ic02a6738a4f1db67a0ddf97b6c93ca32be81789d Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 1f459f1d13..9a96dbcbfc 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -139,7 +139,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() sss.scan(); } - document->jsModule.setFileName(typeData->finalUrlString()); + document->jsModule.fileName = typeData->finalUrlString(); QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); v4CodeGenerator.setUseFastLookups(false); // ### v4CodeGenerator.setUseTypeInference(true); @@ -209,11 +209,6 @@ int QQmlTypeCompiler::registerString(const QString &str) return document->jsGenerator.registerString(str); } -QV4::IR::Module *QQmlTypeCompiler::jsIRModule() const -{ - return &document->jsModule; -} - const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const { return document->javaScriptCompilationUnit->data; -- cgit v1.2.3 From 29e41a9ee61a05274f77f89e9ffd8875f90d3308 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Jun 2017 10:01:17 +0200 Subject: Remove now unused files Remove all files from the old compiler pipeline that are now unused. This includes the whole IR, JIT code generation, and the old Moth Isel. Change-Id: I50d06abfbcf0e9755a54ed94638f8bb74f9512b1 Reviewed-by: Erik Verbruggen --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 9a96dbcbfc..f51546739b 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -46,7 +46,7 @@ #include #include "qqmlpropertycachecreator_p.h" -#include "qv4jssimplifier_p.h" +//#include "qv4jssimplifier_p.h" #define COMPILE_EXCEPTION(token, desc) \ { \ -- cgit v1.2.3 From 540bcf99c5f74f1c3eabdbd6b28265a47e52cd01 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 7 Jul 2017 11:41:02 +0200 Subject: Fix handling of qsTr & friends Translation bindings have a special type. Previously, this was done as a pass on the IR after constant folding: any binding that ended up being a call to qsTr (and friends) was then changed to being a translation binding. Now that we cannot do that anymore, check the AST if the right-hand side of a script binding is a call to qsTr, and go from there. Change-Id: Ibd4f6bc947523652fe2319c1adec6f798b952bbf Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index f51546739b..87c99016f8 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -147,11 +147,6 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() if (!jsCodeGen.generateCodeForComponents()) return nullptr; -#if 0 // ### - QQmlJavaScriptBindingExpressionSimplificationPass pass(document->objects, &document->jsModule, &document->jsGenerator); - pass.reduceTranslationBindings(); -#endif - document->javaScriptCompilationUnit = v4CodeGenerator.generateCompilationUnit(/*generated unit data*/false); } -- cgit v1.2.3 From 49a11e882059ee1729f776722e085dd21d378c36 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 23 Jun 2017 13:20:23 +0200 Subject: Use QQmlType by value QQmlType is now refcounted, and we need to use it by value, to control it's lifetime properly. This is required, so we can clean up the QQmlMetaTypeData cache on engine destruction and with trimComponentCache() Task-number: QTBUG-61536 Change-Id: If86391c86ea20a646ded7c9925d8f743f628fb91 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 53 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index d1d22be0ac..f5cb468479 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -75,7 +75,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() for (auto it = resolvedTypes.constBegin(), end = resolvedTypes.constEnd(); it != end; ++it) { - QQmlCustomParser *customParser = (*it)->type ? (*it)->type->customParser() : 0; + QQmlCustomParser *customParser = (*it)->type.customParser(); if (customParser) customParsers.insert(it.key(), customParser); } @@ -171,7 +171,6 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() compilationUnit->propertyCaches = std::move(m_propertyCaches); Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->data->nObjects)); - if (errors.isEmpty()) return compilationUnit; else @@ -345,11 +344,11 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex); auto *typeRef = resolvedTypes.value(binding->propertyNameIndex); - QQmlType *type = typeRef ? typeRef->type : 0; - if (!type) { + QQmlType type = typeRef ? typeRef->type : nullptr; + if (!type.isValid()) { if (imports->resolveType(propertyName, &type, 0, 0, 0)) { - if (type->isComposite()) { - QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type->sourceUrl()); + if (type.isComposite()) { + QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type.sourceUrl()); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); @@ -361,7 +360,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } } - const QMetaObject *attachedType = type ? type->attachedPropertiesType(enginePrivate) : 0; + const QMetaObject *attachedType = type.attachedPropertiesType(enginePrivate); if (!attachedType) COMPILE_EXCEPTION(binding, tr("Non-existent attached object")); QQmlPropertyCache *cache = compiler->enginePrivate()->cache(attachedType); @@ -418,9 +417,9 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio const QString &originalPropertyName = stringAt(binding->propertyNameIndex); auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); - const QQmlType *type = typeRef ? typeRef->type : 0; - if (type) { - COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type->module()).arg(type->majorVersion()).arg(type->minorVersion())); + const QQmlType type = typeRef->type; + if (type.isValid()) { + COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion())); } else { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName)); } @@ -612,17 +611,17 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, } return true; } - QQmlType *type = 0; + QQmlType type; imports->resolveType(typeName, &type, 0, 0, 0); - if (!type && !isQtObject) + if (!type.isValid() && !isQtObject) return true; int value = 0; bool ok = false; auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex); - if (type && tr && tr->type == type) { + if (type.isValid() && tr && tr->type == type) { QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex()); // When these two match, we can short cut the search @@ -633,8 +632,8 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, } } else { // Otherwise we have to search the whole type - if (type) { - value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok); + if (type.isValid()) { + value = type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok); } else { QByteArray enumName = enumValue.toUtf8(); const QMetaObject *metaObject = StaticQtMetaObject::get(); @@ -657,11 +656,9 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e *ok = false; if (scope != QLatin1String("Qt")) { - QQmlType *type = 0; + QQmlType type; imports->resolveType(scope, &type, 0, 0, 0); - if (!type) - return -1; - return type->enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok); + return type.enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok); } const QMetaObject *mo = StaticQtMetaObject::get(); @@ -799,8 +796,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex); auto *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex); Q_ASSERT(tr); - if (QQmlType *targetType = tr->type) { - if (targetType->metaObject() == &QQmlComponent::staticMetaObject) + if (tr->type.isValid()) { + if (tr->type.metaObject() == &QQmlComponent::staticMetaObject) continue; } else if (tr->compilationUnit) { if (tr->compilationUnit->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject) @@ -829,22 +826,22 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI continue; // emulate "import Qml 2.0 as QmlInternals" and then wrap the component in "QmlInternals.Component {}" - QQmlType *componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject); - Q_ASSERT(componentType); + QQmlType componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject); + Q_ASSERT(componentType.isValid()); const QString qualifier = QStringLiteral("QmlInternals"); - compiler->addImport(componentType->module(), qualifier, componentType->majorVersion(), componentType->minorVersion()); + compiler->addImport(componentType.module(), qualifier, componentType.majorVersion(), componentType.minorVersion()); QmlIR::Object *syntheticComponent = pool->New(); - syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType->elementName()), compiler->registerString(QString())); + syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType.elementName()), compiler->registerString(QString())); syntheticComponent->location = binding->valueLocation; syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent; if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) { auto typeRef = new QV4::CompiledData::ResolvedTypeReference; typeRef->type = componentType; - typeRef->majorVersion = componentType->majorVersion(); - typeRef->minorVersion = componentType->minorVersion(); + typeRef->majorVersion = componentType.majorVersion(); + typeRef->minorVersion = componentType.minorVersion(); resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef); } @@ -885,7 +882,7 @@ bool QQmlComponentAndAliasResolver::resolve() if (obj->inheritedTypeNameIndex) { auto *tref = resolvedTypes->value(obj->inheritedTypeNameIndex); Q_ASSERT(tref); - if (tref->type && tref->type->metaObject() == &QQmlComponent::staticMetaObject) + if (tref->type.metaObject() == &QQmlComponent::staticMetaObject) isExplicitComponent = true; } if (!isExplicitComponent) { -- cgit v1.2.3 From e61dca72682c9f65c6ab6254fc7e80b49be3ad43 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 26 Jun 2017 13:45:56 +0200 Subject: Change data structures in QQmlMetaTypeData Make sure any QQmlType stored in the meta type data has a refcount of 1. This should now make it possible to clean out unused types by iterating over the list of types and removing those that have a refcount of 1. Some care is still needed for C++ registered types, that will need to get one more refcount, so we don't accidentally remove them. Task-number: QTBUG-61536 Change-Id: Id2a18dae5ddcb815f34013f5fde1f05d2d9d0214 Reviewed-by: Simon Hausmann Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index f5cb468479..e17ab354cf 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -344,7 +344,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex); auto *typeRef = resolvedTypes.value(binding->propertyNameIndex); - QQmlType type = typeRef ? typeRef->type : nullptr; + QQmlType type = typeRef ? typeRef->type : QQmlType(); if (!type.isValid()) { if (imports->resolveType(propertyName, &type, 0, 0, 0)) { if (type.isComposite()) { -- cgit v1.2.3 From a32cf1a22d096b33340cddbe91328c6c088e221d Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 6 Sep 2017 16:26:27 +0200 Subject: Disable deferring when referenced as a grouped property This allows us to fix QTBUG-50992 - the issue with most votes in QQC2. Task-number: QTBUG-63036 Change-Id: I996cd1128582b80e0c8480ae143d682c1e8eb8fe Reviewed-by: Simon Hausmann Reviewed-by: Qt CI Bot --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index e17ab354cf..cd7d8ca049 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1251,7 +1251,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex) _seenObjectWithId |= seenSubObjectWithId; } - if (!seenSubObjectWithId + if (!seenSubObjectWithId && binding->type != QV4::CompiledData::Binding::Type_GroupProperty && !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) { binding->flags |= QV4::CompiledData::Binding::IsDeferredBinding; -- cgit v1.2.3 From ebda8170a6b00b830fba59a230506ab3ca52e6c5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 Sep 2017 10:03:48 +0200 Subject: Get rid of the root object index variable This is a follow-up to the parent commit to remove the variable that is really a constant (zero). Change-Id: I8fc20027c5c7b871269b814cb8b93636e94be267 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index cd7d8ca049..eeb5595a9a 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -228,15 +228,10 @@ QVector *QQmlTypeCompiler::qmlObjects() const return &document->objects; } -int QQmlTypeCompiler::rootObjectIndex() const -{ - return document->indexOfRootObject; -} - void QQmlTypeCompiler::setPropertyCaches(QQmlPropertyCacheVector &&caches) { m_propertyCaches = std::move(caches); - Q_ASSERT(m_propertyCaches.count() >= document->indexOfRootObject); + Q_ASSERT(m_propertyCaches.count() > 0); } const QQmlPropertyCacheVector *QQmlTypeCompiler::propertyCaches() const @@ -680,7 +675,7 @@ QQmlCustomParserScriptIndexer::QQmlCustomParserScriptIndexer(QQmlTypeCompiler *t void QQmlCustomParserScriptIndexer::annotateBindingsWithScriptStrings() { - scanObjectRecursively(compiler->rootObjectIndex()); + scanObjectRecursively(/*root object*/0); } void QQmlCustomParserScriptIndexer::scanObjectRecursively(int objectIndex, bool annotateScriptBindings) @@ -775,7 +770,6 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t , enginePrivate(typeCompiler->enginePrivate()) , pool(typeCompiler->memoryPool()) , qmlObjects(typeCompiler->qmlObjects()) - , indexOfRootObject(typeCompiler->rootObjectIndex()) , resolvedTypes(&typeCompiler->resolvedTypes) , propertyCaches(std::move(typeCompiler->takePropertyCaches())) { @@ -913,9 +907,9 @@ bool QQmlComponentAndAliasResolver::resolve() if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object) COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); - // We are going to collect ids/aliases and resolve them for the root object as a separate + // For the root object, we are going to collect ids/aliases and resolve them for as a separate // last pass. - if (i != indexOfRootObject) + if (i != 0) componentRoots.append(i); } @@ -941,12 +935,12 @@ bool QQmlComponentAndAliasResolver::resolve() _idToObjectIndex.clear(); _objectsWithAliases.clear(); - collectIdsAndAliases(indexOfRootObject); + collectIdsAndAliases(/*root object*/0); - QmlIR::Object *rootComponent = qmlObjects->at(indexOfRootObject); + QmlIR::Object *rootComponent = qmlObjects->at(/*root object*/0); rootComponent->namedObjectsInComponent.allocate(pool, _idToObjectIndex); - if (!resolveAliases(indexOfRootObject)) + if (!resolveAliases(/*root object*/0)) return false; // Implicit component insertion may have added objects and thus we also need @@ -974,7 +968,7 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex) _objectsWithAliases.append(objectIndex); // Stop at Component boundary - if (obj->flags & QV4::CompiledData::Object::IsComponent && objectIndex != compiler->rootObjectIndex()) + if (obj->flags & QV4::CompiledData::Object::IsComponent && objectIndex != /*root object*/0) return true; for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { @@ -1165,7 +1159,7 @@ QQmlDeferredAndCustomParserBindingScanner::QQmlDeferredAndCustomParserBindingSca bool QQmlDeferredAndCustomParserBindingScanner::scanObject() { - return scanObject(compiler->rootObjectIndex()); + return scanObject(/*root object*/0); } bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex) @@ -1291,7 +1285,7 @@ bool QQmlJSCodeGenerator::generateCodeForComponents() return false; } - return compileComponent(compiler->rootObjectIndex()); + return compileComponent(/*root object*/0); } bool QQmlJSCodeGenerator::compileComponent(int contextObject) -- cgit v1.2.3 From d8593011d2d01a04a01e7bf369caa166d91b3d6a Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 18 Sep 2017 18:12:40 +0200 Subject: Fix crash when using signal handlers on group properties This is a regression introduced with commmit 49a11e882059ee1729f776722e085dd21d378c36: The typeRef can be null. I found this when testing grouped properties and property revisions. import QtQuick 2.0 Item { property alias textEdit: textEdit TextEdit { id: textEdit } } import QtQuick 2.8 Item { TestComponent { textEdit.onEditingFinished: console.log("test") } } Instead of an error message, this crashes without this patch. This is a regression introduced by using QQmlType by value. Change-Id: Ib18a0ad878f7c4696c22bc65fee636b84b966f03 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index eeb5595a9a..fab865081a 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -412,7 +412,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio const QString &originalPropertyName = stringAt(binding->propertyNameIndex); auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); - const QQmlType type = typeRef->type; + const QQmlType type = typeRef ? typeRef->type : QQmlType(); if (type.isValid()) { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion())); } else { -- cgit v1.2.3 From 0855417be493a774c1d1a70fcf7a73ee7fed0529 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 24 Oct 2017 13:56:09 +0200 Subject: Re-enable Debug instructions and locations for QML functions Debug instructions are used to trigger break points and are added for every source line. We also need to insert Debug instructions before Ret, so that we can step out. We also need to assign line numbers to the entry and return points of "abbreviated" QML functions (by simulating lbrace and rbrace) so that we can set break points on them. The line numbers on Ret need to be negative, so that you cannot (accidentally) set break points on them. A typical signal handler or binding in QML consists of only one line and if you set a break point on that line, you want it to hit only once, when entering the function. If the line numbers on Ret were positive, it would be hit again on exit. Some of the tests in tst_qqmldebugjs implicitly check for that. Also the new interpreter does something on the left brace, so a function actually starts there, not on the first statement. Change-Id: Id9dfb20e35696b420d0950deab988f7cc5197bfc Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 1e17312fe1..2bee00552f 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -491,7 +491,9 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements); functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body); - functionDeclaration->functionToken = foe->node->firstSourceLocation(); + functionDeclaration->lbraceToken = functionDeclaration->functionToken + = foe->node->firstSourceLocation(); + functionDeclaration->rbraceToken = foe->node->lastSourceLocation(); } foe->node = functionDeclaration; binding->propertyNameIndex = compiler->registerString(propertyName); -- cgit v1.2.3 From 52bc4fbfbae6aa1569dc134dd103e966f04bc2e6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 11 Dec 2017 12:44:47 +0100 Subject: Use potentially intercepted URL as ID for compilation units We generally have to pass a URL and a file name everywhere because the logical URL might be something else than the actual file being loaded. For example a QQmlFileSelector might modify the URL to be loaded for a specific file. This resulting URL, however, should not be used to resolve further URLs defined in the file loaded that way. As we need to access QQmlTypeLoader::m_url as string more often now, cache it and avoid frequent translations between QUrl and QString. Furthermore, QQmlDataBlob's URLs are changed to follow the same semantics. The finalUrl is the one that should be used to resolve further URLs, the url is the one used to load the content, and subject to any redirects or interceptions. This changes the semantics of URL redirects. Previously a redirected URL was used as the base URL for furher URL resolution. This doesn't work because redirection occurs after interception and interception should not influence the resolution of further URLs. We now use the original URL as base URL for resolution of further URLs and rely on the server to redirect those, too. Task-number: QTBUG-61209 Change-Id: I93822f820bed2515995de3cb118099218b510ca4 Reviewed-by: Michael Brasser --- src/qml/compiler/qqmltypecompiler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index fab865081a..568ad4af89 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -140,7 +140,10 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() sss.scan(); } - QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); + QmlIR::JSCodeGen v4CodeGenerator(typeData->urlString(), typeData->finalUrlString(), + document->code, &document->jsModule, + &document->jsParserEngine, document->program, + typeNameCache, &document->jsGenerator.stringTable); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; -- cgit v1.2.3 From ccee761f06be0f62b84f944a76b0aa4dc759091f Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 4 Jan 2018 14:52:56 +0100 Subject: Fix segfault on invalid property alias syntax Task-number: QTBUG-64798 Change-Id: Id1eb434f83ec89c5ea1ebaa4d8ec86fce9f4428f Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 568ad4af89..0dd3cf9bfa 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1080,7 +1080,11 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject; } else { QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex); - Q_ASSERT(targetCache); + if (!targetCache) { + *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString())); + break; + } + QmlIR::PropertyResolver resolver(targetCache); QQmlPropertyData *targetProperty = resolver.property(property.toString()); -- cgit v1.2.3 From 9643635f867b67e263d1c615965a93a1579f8b34 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 14 Sep 2017 14:38:36 +0200 Subject: Allow exported signal handlers for signals with revision Properties of QML objects or alias properties to QML objects have to know about the revision of the QML type. If the property is used as a grouped property and a signal or property is assigned. Without this patch this is not working with signals that have a revision. To get this working we store the minor version of the QML type in QQmlPropertyData and retrieve the QQmlPropertyCache with the correct AllowedRevisionCache using this minor version. Task-number: QTCREATORBUG-18820 Change-Id: I1e20169e0d5a2ae11059a951aa83a5c94106accb Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 97ca597953..836aa8c416 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -823,7 +823,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI if (!pd || !pd->isQObject()) continue; - QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType()); + QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeMinorVersion()); const QMetaObject *mo = pc ? pc->firstCppMetaObject() : 0; while (mo) { if (mo == &QQmlComponent::staticMetaObject) -- cgit v1.2.3 From c2b4c6393fee37e0c6c4a8c5d40d13120cc8a94e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 15 Jan 2018 15:36:25 +0100 Subject: Use a more optimized lookup for global properties Force the use of a global lookup if we know that the property can and will be found in the global object. This is possible, as the global object is frozen in QML mode and can't be overwritten. Shaves of .5% on the delegates_item_states benchmark, and will significantly speed up all accesses to e.g. the Math object. Change-Id: Ia1e248781a13ebaeb8bc43652e53a6fdde336d0d Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 0dd3cf9bfa..d152d26968 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -143,7 +143,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() QmlIR::JSCodeGen v4CodeGenerator(typeData->urlString(), typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, - typeNameCache, &document->jsGenerator.stringTable); + typeNameCache, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames()); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; -- cgit v1.2.3 From eec58534ab9c3fae74a1b4cb0861d4b40253cd2d Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 10 Jan 2018 13:51:23 +0100 Subject: Fix segfault when alias target refers to lowercase-named type Create an error via QQmlCompileError and return it instead of asserting. Task-number: QTBUG-43567 Change-Id: I0c0741943d30516379eff5f44ed8618a0f0116a4 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index d152d26968..0eae909cf7 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1010,7 +1010,11 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) } if (result == AllAliasesResolved) { - aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); + QQmlCompileError error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); + if (error.isSet()) { + recordError(error); + return false; + } atLeastOneAliasResolved = true; } else if (result == SomeAliasesResolved) { atLeastOneAliasResolved = true; -- cgit v1.2.3 From 65606ea1559572d66ee8bfac77e87f3e8f447c3e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 19 Dec 2017 11:14:27 +0100 Subject: Remove double indirection between QJSEngine and QV4::ExecutionEngine As QJSEngine's handle() method is internal, we can redefine it to return a pointer to an ExecutionEngine. That makes many things easier. Change-Id: Ie3df99e0bad5f00ad4fe73182896cd135fa82994 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 836aa8c416..62bddd2509 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -295,7 +295,7 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler) , imports(typeCompiler->imports()) , customParsers(typeCompiler->customParserCache()) , resolvedTypes(typeCompiler->resolvedTypes) - , illegalNames(QV8Engine::get(QQmlEnginePrivate::get(typeCompiler->enginePrivate()))->illegalNames()) + , illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames()) , propertyCaches(typeCompiler->propertyCaches()) { } -- cgit v1.2.3 From 499ec43937e926e4f2fa57a9baa455fcb3862262 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 21 Feb 2018 10:41:54 +0100 Subject: use nullptr consistently (clang-tidy) From now on we prefer nullptr instead of 0 to clarify cases where we are assigning or testing a pointer rather than a numeric zero. Also, replaced cases where 0 was passed as Qt::KeyboardModifiers with Qt::NoModifier (clang-tidy replaced them with nullptr, which waas wrong, so it was just as well to make the tests more readable rather than to revert those lines). Change-Id: I4735d35e4d9f42db5216862ce091429eadc6e65d Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index ac373aafb4..3415e1c073 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -332,7 +332,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio auto *typeRef = resolvedTypes.value(binding->propertyNameIndex); QQmlType type = typeRef ? typeRef->type : QQmlType(); if (!type.isValid()) { - if (imports->resolveType(propertyName, &type, 0, 0, 0)) { + if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) { if (type.isComposite()) { QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type.sourceUrl()); Q_ASSERT(tdata); @@ -397,7 +397,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } else { if (notInRevision) { // Try assinging it as a property later - if (resolver.property(propertyName, /*notInRevision ptr*/0)) + if (resolver.property(propertyName, /*notInRevision ptr*/nullptr)) continue; const QString &originalPropertyName = stringAt(binding->propertyNameIndex); @@ -457,7 +457,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio QQmlJS::MemoryPool *pool = compiler->memoryPool(); - QQmlJS::AST::FormalParameterList *paramList = 0; + QQmlJS::AST::FormalParameterList *paramList = nullptr; for (const QString ¶m : qAsConst(parameters)) { QStringRef paramNameRef = compiler->newStringRef(param); @@ -471,7 +471,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio paramList = paramList->finish(); QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex); - QQmlJS::AST::FunctionDeclaration *functionDeclaration = 0; + QQmlJS::AST::FunctionDeclaration *functionDeclaration = nullptr; if (QQmlJS::AST::ExpressionStatement *es = QQmlJS::AST::cast(foe->node)) { if (QQmlJS::AST::FunctionExpression *fe = QQmlJS::AST::cast(es->expression)) { functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(fe->name, fe->formals, fe->body); @@ -611,7 +611,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, return true; } QQmlType type; - imports->resolveType(typeName, &type, 0, 0, 0); + imports->resolveType(typeName, &type, nullptr, nullptr, nullptr); if (!type.isValid() && !isQtObject) return true; @@ -663,7 +663,7 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QStringRef &e if (scope != QLatin1String("Qt")) { QQmlType type; - imports->resolveType(scope, &type, 0, 0, 0); + imports->resolveType(scope, &type, nullptr, nullptr, nullptr); if (!type.isValid()) return -1; if (!enumName.isEmpty()) @@ -814,7 +814,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI continue; } - QQmlPropertyData *pd = 0; + QQmlPropertyData *pd = nullptr; if (binding->propertyNameIndex != quint32(0)) { bool notInRevision = false; pd = propertyResolver.property(stringAt(binding->propertyNameIndex), ¬InRevision); @@ -825,7 +825,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI continue; QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeMinorVersion()); - const QMetaObject *mo = pc ? pc->firstCppMetaObject() : 0; + const QMetaObject *mo = pc ? pc->firstCppMetaObject() : nullptr; while (mo) { if (mo == &QQmlComponent::staticMetaObject) break; @@ -1204,7 +1204,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex) return true; QString defaultPropertyName; - QQmlPropertyData *defaultProperty = 0; + QQmlPropertyData *defaultProperty = nullptr; if (obj->indexOfDefaultPropertyOrAlias != -1) { QQmlPropertyCache *cache = propertyCache->parent(); defaultPropertyName = cache->defaultPropertyName(); @@ -1229,7 +1229,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex) } for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - QQmlPropertyData *pd = 0; + QQmlPropertyData *pd = nullptr; QString name = stringAt(binding->propertyNameIndex); if (customParser) { @@ -1334,7 +1334,7 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject) auto *tref = resolvedTypes.value(obj->inheritedTypeNameIndex); if (tref && tref->isFullyDynamicType) - m.type = 0; + m.type = nullptr; idMapping << m; } @@ -1412,10 +1412,10 @@ void QQmlDefaultPropertyMerger::mergeDefaultProperties(int objectIndex) QmlIR::Object *object = qmlObjects.at(objectIndex); QString defaultProperty = object->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName(); - QmlIR::Binding *bindingsToReinsert = 0; - QmlIR::Binding *tail = 0; + QmlIR::Binding *bindingsToReinsert = nullptr; + QmlIR::Binding *tail = nullptr; - QmlIR::Binding *previousBinding = 0; + QmlIR::Binding *previousBinding = nullptr; QmlIR::Binding *binding = object->firstBinding(); while (binding) { if (binding->propertyNameIndex == quint32(0) || stringAt(binding->propertyNameIndex) != defaultProperty) { @@ -1434,7 +1434,7 @@ void QQmlDefaultPropertyMerger::mergeDefaultProperties(int objectIndex) tail->next = toReinsert; tail = tail->next; } - tail->next = 0; + tail->next = nullptr; } binding = bindingsToReinsert; -- cgit v1.2.3 From 50f700aa8f68fff1e0153d19227b5a0bebbb6e51 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Feb 2018 16:04:08 +0100 Subject: Fix group property bindings for aliases that point to id objects When declaring bindings within a group property and that group property itself is a locally declared alias, then by the time we try to determine property caches for the group property we will fail as the aliases haven't been resolved yet. To fix this we can keep track of such group property declarations (encapsulated in the QQmlInstantiatingBindingContext that has all we need) and after we've resolved the aliases (added them to the property caches), we can go back and fill in the entries in the propertyCaches array for the group properties. Task-number: QTBUG-51043 Change-Id: I5613513db3977934bcc51a3df530de47d57326f9 Reviewed-by: Mitch Curtis Reviewed-by: Michael Brasser --- src/qml/compiler/qqmltypecompiler.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 3415e1c073..a896745b3f 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -45,7 +45,6 @@ #include #include -#include "qqmlpropertycachecreator_p.h" //#include "qv4jssimplifier_p.h" #define COMPILE_EXCEPTION(token, desc) \ @@ -79,8 +78,12 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() customParsers.insert(it.key(), customParser); } + QQmlPendingGroupPropertyBindings pendingGroupPropertyBindings; + + { - QQmlPropertyCacheCreator propertyCacheBuilder(&m_propertyCaches, engine, this, imports()); + QQmlPropertyCacheCreator propertyCacheBuilder(&m_propertyCaches, &pendingGroupPropertyBindings, + engine, this, imports()); QQmlCompileError error = propertyCacheBuilder.buildMetaObjects(); if (error.isSet()) { recordError(error); @@ -122,6 +125,8 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() QQmlComponentAndAliasResolver resolver(this); if (!resolver.resolve()) return nullptr; + + pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_propertyCaches); } { -- cgit v1.2.3 From da5fffbd34d8be68f8ee4c649881dbb673c9c0a5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 10 Feb 2018 23:22:13 +0100 Subject: Partially support binding patterns Destructuring objects works, but arrays are not yet supported. Change-Id: I61e917e1964e3c719f71b8f11d194e09dfe288c2 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a896745b3f..7c8bf05ce5 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -466,10 +466,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio for (const QString ¶m : qAsConst(parameters)) { QStringRef paramNameRef = compiler->newStringRef(param); - if (paramList) - paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, paramNameRef); - else - paramList = new (pool) QQmlJS::AST::FormalParameterList(paramNameRef); + QQmlJS::AST::BindingElement *b = new (pool) QQmlJS::AST::BindingElement(paramNameRef, nullptr); + paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, b); } if (paramList) -- cgit v1.2.3 From 70251c5ee7e2c96dac19e49b6ce69a55d78994a4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 2 Mar 2018 11:02:06 +0100 Subject: Bring JS grammar in line with ES7 spec This basically updates all grammar rules in the qqmljs.g file to be in line with the ES7 specification. Some special handling for the lookahead rules appearing in the spec was needed and is implemented through empty lookahead rules in the grammar, that might push an additional token into the token stream. Renamed some classes in the AST to be in line with the names used in ES7, and removed some other ones (SourceElements) that are no longer used. The ES7 grammar rules contain lots of variations of the base rules (with In/Return/Yield/Default suffixes). With the exception of the In and Default rules, these are implemented through state tracking in the parser and lexer. Change-Id: I4017d97cd050ed816c1dad11833e882cba30801a Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 7c8bf05ce5..34c2c3ffc9 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -488,11 +488,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } if (!functionDeclaration) { QQmlJS::AST::Statement *statement = static_cast(foe->node); - QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement); - QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement); - elements = elements->finish(); - - QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements); + QQmlJS::AST::StatementList *body = new (pool) QQmlJS::AST::StatementList(statement); + body = body->finish(); functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body); functionDeclaration->lbraceToken = functionDeclaration->functionToken -- cgit v1.2.3 From 1a3447a0405831fa5502247f9eaff48afdfe0dea Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 Apr 2018 13:28:58 +0200 Subject: Clean up manual reference of QQmlTypeData and QQmlPropertyCache We have a few places in the type loader where we do adventurous manual reference counting, where getType() returns a raw pointer that has been addref()'ed and then sometimes somehow we call release() later. Commit 0b394e30bba4f6bb7e6f7dbe5585a2e15aa0f21d is an example of where this can easily go wrong. As a consequence and also in preparation for future work on the type loader, this patch starts replacing the manual reference counting there. Changing the return type from QQmlTypeData *getType() to a QQmlRefPointer<> itself is not sufficient though, as the implicit operator T*() will still allow the caller to store the result as a raw pointer. Therefore this patch removes the "unsafe" implicit extraction operator. As a result of that change, other types that are sometimes stored in QQmlRefPointer are also affected and their usage needs to be adapted to QQmlRefPointer usage or manual raw pointer extraction with .data(). Change-Id: I18fd40634047f13196a237f4e6766cbef3bfbea2 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 34c2c3ffc9..d1e4041b7e 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -67,7 +67,7 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *type { } -QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() +QQmlRefPointer QQmlTypeCompiler::compile() { // Build property caches and VME meta object data @@ -147,7 +147,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() document->jsModule.fileName = typeData->urlString(); document->jsModule.finalUrl = typeData->finalUrlString(); QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, - document->program, typeNameCache, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames()); + document->program, typeNameCache.data(), &document->jsGenerator.stringTable, engine->v8engine()->illegalNames()); v4CodeGenerator.setUseFastLookups(false); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) @@ -165,7 +165,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() // The js unit owns the data and will free the qml unit. document->javaScriptCompilationUnit->data = qmlUnit; - QV4::CompiledData::CompilationUnit *compilationUnit = document->javaScriptCompilationUnit; + QQmlRefPointer compilationUnit = document->javaScriptCompilationUnit; compilationUnit = document->javaScriptCompilationUnit; compilationUnit->typeNameCache = typeNameCache; compilationUnit->resolvedTypes = resolvedTypes; @@ -339,14 +339,12 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio if (!type.isValid()) { if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) { if (type.isComposite()) { - QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type.sourceUrl()); + QQmlRefPointer tdata = enginePrivate->typeLoader.getType(type.sourceUrl()); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); auto compilationUnit = tdata->compilationUnit(); type = QQmlMetaType::qmlType(compilationUnit->metaTypeId); - - tdata->release(); } } } -- cgit v1.2.3 From 02252ae08dc36ba44f65fb932c428849c7369299 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Mar 2018 16:34:05 +0100 Subject: Rework the AST for Literals and destructuring expressions Array/ObjectLiterals and destructuring expressions are syntactically very similar. In some cases (when using a destructuring expression as the lhs of an assigment), the parser needs to convert the literal into a destructuring expression. To support these, use the same data structures for both in the AST. Those Patterns can be converted with little additional work from a Literal to an AssignmentPattern and be used in all places where we need destructuring in addition to literals. Change-Id: I177599b46eab0f6e8cb2a40c3b3b11ed00a07d6a Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index d1e4041b7e..76245ced1d 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -464,7 +464,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio for (const QString ¶m : qAsConst(parameters)) { QStringRef paramNameRef = compiler->newStringRef(param); - QQmlJS::AST::BindingElement *b = new (pool) QQmlJS::AST::BindingElement(paramNameRef, nullptr); + QQmlJS::AST::PatternElement *b = new (pool) QQmlJS::AST::PatternElement(paramNameRef, nullptr); paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, b); } -- cgit v1.2.3 From d5adc61b1fe358f7ba5d3570305eaf0733426e2f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 15 Jun 2018 09:03:53 +0200 Subject: Fix string memory leak in JavaScript AST Commit 02252ae08d introduced a QString member in a JS memory pool class, which leaks unfortunately as the pool is not designed to call destructors of allocated types. Typically strings in the AST are derived from input and therefore a QStringRef is fine. The bindingIdentifier in the PatterElement however is sometimes synthesized, so a separate storage for dynamically allocated strings in the memory pool allows for using QStringRef again. Change-Id: I94d090df653d784c554452722b3b759031e4735b Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 76245ced1d..37271e2c54 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -469,7 +469,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } if (paramList) - paramList = paramList->finish(); + paramList = paramList->finish(pool); QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex); QQmlJS::AST::FunctionDeclaration *functionDeclaration = nullptr; -- cgit v1.2.3 From da1a6606f5520e58a43030735ad608f40fdfc346 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 20 Jul 2018 17:08:04 +0200 Subject: Remove unused code as discussed on IRC Change-Id: Id15127990a4263d92761c8dc8265513041553ddc Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 37271e2c54..0d338c8b7e 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -45,8 +45,6 @@ #include #include -//#include "qv4jssimplifier_p.h" - #define COMPILE_EXCEPTION(token, desc) \ { \ recordError((token)->location, desc); \ -- cgit v1.2.3 From e56eeee9902ffc341506040e637654b2b0451209 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 Jul 2018 10:40:41 +0200 Subject: Encapsulate the unit data in CompilationUnit This allows updating the constants table when the unit data is set / changes and removes the tie to the engine. Change-Id: Ice553650390589e30e18421c4e55422a55d0df89 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 0d338c8b7e..6582a9ca6b 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -161,14 +161,14 @@ QQmlRefPointer QQmlTypeCompiler::compile() Q_ASSERT(document->javaScriptCompilationUnit); // The js unit owns the data and will free the qml unit. - document->javaScriptCompilationUnit->data = qmlUnit; + document->javaScriptCompilationUnit->setUnitData(qmlUnit); QQmlRefPointer compilationUnit = document->javaScriptCompilationUnit; compilationUnit = document->javaScriptCompilationUnit; compilationUnit->typeNameCache = typeNameCache; compilationUnit->resolvedTypes = resolvedTypes; compilationUnit->propertyCaches = std::move(m_propertyCaches); - Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->data->nObjects)); + Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->unitData()->nObjects)); if (errors.isEmpty()) return compilationUnit; @@ -209,7 +209,7 @@ int QQmlTypeCompiler::registerString(const QString &str) const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const { - return document->javaScriptCompilationUnit->data; + return document->javaScriptCompilationUnit->unitData(); } const QQmlImports *QQmlTypeCompiler::imports() const -- cgit v1.2.3 From fcf9b7efa5b2a0d8f49e59b2a977b8122632aff6 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 20 Jul 2018 15:19:17 +0200 Subject: Clean up constant storage for CompiledData::Binding Store doubles in bindings in the constant table of the compilation unit instead of each binding. This removes one of the two 8 byte members of the value union and also allows for sharing of constants throughout a .qml file. Change-Id: I1d7daafdb7f24e34c14cd160d2dcb2c5aaac1c50 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 6582a9ca6b..a6bdf93e2e 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -207,6 +207,11 @@ int QQmlTypeCompiler::registerString(const QString &str) return document->jsGenerator.registerString(str); } +int QQmlTypeCompiler::registerConstant(QV4::ReturnedValue v) +{ + return document->jsGenerator.registerConstant(v); +} + const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const { return document->javaScriptCompilationUnit->unitData(); @@ -555,7 +560,8 @@ bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QS COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName.toString())); } binding->type = QV4::CompiledData::Binding::Type_Number; - binding->setNumberValueInternal((double)enumValue); + binding->value.constantValueIndex = compiler->registerConstant(QV4::Encode((double)enumValue)); +// binding->setNumberValueInternal((double)enumValue); binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum; return true; } -- cgit v1.2.3 From 8237f645a33199e0a8aded0a3f7e6077990707fd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 23 Jul 2018 14:08:06 +0200 Subject: Optimize memory consumption of ahead-of-time compile cache files When loading a pre-compiled cache file, the strings contained therein will remain available in memory since commit 7dcada48d2435e8ceb0cc8a6771f79b76979e11f. While for aot built cache files we may have to add new strings (for example for signal handler parameters), we can re-use the existing strings by omitting them from the intermediately created string table. This saves ~283K RAM with qtquickcontrols1 gallery. Task-number: QTBUG-69588 Change-Id: I8ea807f6dea4cc35d8b7e5f7329809ed1cd12880 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a6bdf93e2e..15edc010fd 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -133,8 +133,12 @@ QQmlRefPointer QQmlTypeCompiler::compile() return nullptr; } - // Compile JS binding expressions and signal handlers - if (!document->javaScriptCompilationUnit) { + if (document->javaScriptCompilationUnit) { + // If this file was loaded from an ahead-of-time built cache file, then set up the original + // unit data as backing unit and fetch strings from there to save memory. + document->javaScriptCompilationUnit->backingUnit = document->javaScriptCompilationUnit->unitData(); + } else { + // Compile JS binding expressions and signal handlers if necessary { // We can compile script strings ahead of time, but they must be compiled // without type optimizations as their scope is always entirely dynamic. -- cgit v1.2.3 From 193db4c52613a37275535783825190ddd7e1f758 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 26 Jul 2018 11:05:08 +0200 Subject: Clean up internal QML unit creation API Since the callers always end up assigning the returned unit pointer back to the compilation unit's data member, we might as well do that inside the function and return void instead. Change-Id: I7a7f3e7a0c89ffe2f9474149fcf61736609b363d Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 15edc010fd..c4a3d47f44 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -161,11 +161,7 @@ QQmlRefPointer QQmlTypeCompiler::compile() // Generate QML compiled type data structures QmlIR::QmlUnitGenerator qmlGenerator; - QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document, dependencyHasher); - - Q_ASSERT(document->javaScriptCompilationUnit); - // The js unit owns the data and will free the qml unit. - document->javaScriptCompilationUnit->setUnitData(qmlUnit); + qmlGenerator.generate(*document, dependencyHasher); QQmlRefPointer compilationUnit = document->javaScriptCompilationUnit; compilationUnit = document->javaScriptCompilationUnit; -- cgit v1.2.3 From 77449db6e086e8ac6594c432fede027656be0da0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 27 Jul 2018 11:36:43 +0200 Subject: Encapsulate access to CompiledData::Object and CompiledData::Import This will make it easier to move the data out of CompiledData::Unit and into a separate data structure. Change-Id: I32e6233a66f2279b44cc06ef7c3505db4a565f98 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index c4a3d47f44..44ffc864a8 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -168,7 +168,7 @@ QQmlRefPointer QQmlTypeCompiler::compile() compilationUnit->typeNameCache = typeNameCache; compilationUnit->resolvedTypes = resolvedTypes; compilationUnit->propertyCaches = std::move(m_propertyCaches); - Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->unitData()->nObjects)); + Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->objectCount())); if (errors.isEmpty()) return compilationUnit; -- cgit v1.2.3 From e99038b24d8b9f4a8cc503d1e3f789a93a3e8330 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 27 Jul 2018 11:47:53 +0200 Subject: Reduce memory consumption when loading AOT generated cache files Separate the qml data (objects/imports) from the general compilation unit data. It's only the former that needs to be re-generated as part of the type re-compilation and by separating it we can allocate memory just for that and keep using the mmap'ed general unit data for everything else (including byte code). Another upside of this change is that it allows eliminating the recently introduced concept of a backing unit again. Saves ~149K RAM with the QQC1 gallery. Task-number: QTBUG-69588 Change-Id: Ie88a4286feb7e2f472f58a28fa5dd6ff0a91c4b6 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmltypecompiler.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 44ffc864a8..1695f3e5d6 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -133,11 +133,7 @@ QQmlRefPointer QQmlTypeCompiler::compile() return nullptr; } - if (document->javaScriptCompilationUnit) { - // If this file was loaded from an ahead-of-time built cache file, then set up the original - // unit data as backing unit and fetch strings from there to save memory. - document->javaScriptCompilationUnit->backingUnit = document->javaScriptCompilationUnit->unitData(); - } else { + if (!document->javaScriptCompilationUnit) { // Compile JS binding expressions and signal handlers if necessary { // We can compile script strings ahead of time, but they must be compiled -- cgit v1.2.3 From 607ced5bfd1390de4342bb44ab99e7acafd9f4e9 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Wed, 9 May 2018 17:16:59 +0200 Subject: Allow DelegateModel-based views to support multiple delegate types This patch adds a specific abstract QQmlComponent subclass, QQmlAbstractDelegateComponent, and a default implementation, DelegateChooser, that, together with the type DelegateChoice allows determining the delegate type by role and/or index. The patch also adds QQmlAbstractDelegateComponent support to QQmlTableInstanceModel, that is a simplified version of the delegate model, currently only used in the new table view. DelegateChoosers are intended to behave just like Components in the context of the view. This means that they can be declared outside of the view, and also in separate files, and the same delegate component can be used at the same time in multiple views. [ChangeLog][QtQuick][Item Views] Added a DelegateChooser Component to host DelegateChoice instances to choose different delegates in an Item View (e.g. TableView) depending on model roles. Done-with: Michael Brasser Task-number: QTBUG-26681 Change-Id: Ibe24a31daf9142c8a9ff45ef6c65da0aec8a14dc Reviewed-by: Shawn Rutledge --- src/qml/compiler/qqmltypecompiler.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 1695f3e5d6..a03f69576d 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #define COMPILE_EXCEPTION(token, desc) \ { \ @@ -804,13 +805,21 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex); auto *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex); Q_ASSERT(tr); - if (tr->type.isValid()) { - if (tr->type.metaObject() == &QQmlComponent::staticMetaObject) - continue; - } else if (tr->compilationUnit) { - if (tr->compilationUnit->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject) - continue; - } + + const QMetaObject *firstMetaObject = nullptr; + if (tr->type.isValid()) + firstMetaObject = tr->type.metaObject(); + else if (tr->compilationUnit) + firstMetaObject = tr->compilationUnit->rootPropertyCache()->firstCppMetaObject(); + // 1: test for QQmlComponent + if (firstMetaObject && firstMetaObject == &QQmlComponent::staticMetaObject) + continue; + // 2: test for QQmlAbstractDelegateComponent + while (firstMetaObject && firstMetaObject != &QQmlAbstractDelegateComponent::staticMetaObject) + firstMetaObject = firstMetaObject->superClass(); + if (firstMetaObject) + continue; + // if here, not a QQmlComponent or a QQmlAbstractDelegateComponent, so needs wrapping QQmlPropertyData *pd = nullptr; if (binding->propertyNameIndex != quint32(0)) { -- cgit v1.2.3 From 923fef3ad3076e337eba4e603a6f759c54cc404c Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 23 Nov 2018 12:27:55 +0100 Subject: V4: Move the FixedPoolArray into the MemoryPool header So now the FixedPoolArray can be re-used in other places. Change-Id: I0e0504892944722a0c18f207dc6400d5b314f6ae Reviewed-by: Ulf Hermann --- src/qml/compiler/qqmltypecompiler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a03f69576d..cb097a0410 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1330,8 +1330,8 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject) } QmlIR::JSCodeGen::ObjectIdMapping idMapping; - idMapping.reserve(obj->namedObjectsInComponent.count); - for (int i = 0; i < obj->namedObjectsInComponent.count; ++i) { + idMapping.reserve(obj->namedObjectsInComponent.size()); + for (int i = 0; i < obj->namedObjectsInComponent.size(); ++i) { const int objectIndex = obj->namedObjectsInComponent.at(i); QmlIR::JSCodeGen::IdMapping m; const QmlIR::Object *obj = qmlObjects.at(objectIndex); -- cgit v1.2.3 From 06ec6340d0eff763e52135afabc13662b3892c43 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 18 Feb 2019 14:24:45 +0100 Subject: Avoid unnecessary re-generation qml cache files in some circumstances The map of name IDs to resolved types so far is copied several times during compilation and different compile passes see different copies of it. Compile passes may add things to the map, and if they do that on copies that are inaccessible to other code, we get nondeterministic results. Furthermore all the copies and pointers are confusing and inefficient. Fixes: QTBUG-69340 Change-Id: I43ad3cbeeec34f90e05570eddc901fe8aa64c709 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'src/qml/compiler/qqmltypecompiler.cpp') diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a03f69576d..75ed8dd10f 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, - const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) + QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher) : resolvedTypes(resolvedTypeCache) , engine(engine) , typeData(typeData) @@ -70,7 +70,7 @@ QQmlRefPointer QQmlTypeCompiler::compile() { // Build property caches and VME meta object data - for (auto it = resolvedTypes.constBegin(), end = resolvedTypes.constEnd(); + for (auto it = resolvedTypes->constBegin(), end = resolvedTypes->constEnd(); it != end; ++it) { QQmlCustomParser *customParser = (*it)->type.customParser(); if (customParser) @@ -161,9 +161,8 @@ QQmlRefPointer QQmlTypeCompiler::compile() qmlGenerator.generate(*document, dependencyHasher); QQmlRefPointer compilationUnit = document->javaScriptCompilationUnit; - compilationUnit = document->javaScriptCompilationUnit; compilationUnit->typeNameCache = typeNameCache; - compilationUnit->resolvedTypes = resolvedTypes; + compilationUnit->resolvedTypes = *resolvedTypes; compilationUnit->propertyCaches = std::move(m_propertyCaches); Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->objectCount())); @@ -300,7 +299,6 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler) , qmlObjects(*typeCompiler->qmlObjects()) , imports(typeCompiler->imports()) , customParsers(typeCompiler->customParserCache()) - , resolvedTypes(typeCompiler->resolvedTypes) , illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames()) , propertyCaches(typeCompiler->propertyCaches()) { @@ -334,7 +332,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio // Attached property? if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex); - auto *typeRef = resolvedTypes.value(binding->propertyNameIndex); + auto *typeRef = resolvedType(binding->propertyNameIndex); QQmlType type = typeRef ? typeRef->type : QQmlType(); if (!type.isValid()) { if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) { @@ -405,7 +403,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio const QString &originalPropertyName = stringAt(binding->propertyNameIndex); - auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); + auto *typeRef = resolvedType(obj->inheritedTypeNameIndex); const QQmlType type = typeRef ? typeRef->type : QQmlType(); if (type.isValid()) { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion())); @@ -506,7 +504,6 @@ QQmlEnumTypeResolver::QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler) , qmlObjects(*typeCompiler->qmlObjects()) , propertyCaches(typeCompiler->propertyCaches()) , imports(typeCompiler->imports()) - , resolvedTypes(&typeCompiler->resolvedTypes) { } @@ -618,7 +615,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, int value = 0; bool ok = false; - auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex); + auto *tr = resolvedType(obj->inheritedTypeNameIndex); if (type.isValid() && tr && tr->type == type) { // When these two match, we can short cut the search QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex()); @@ -785,7 +782,6 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t , enginePrivate(typeCompiler->enginePrivate()) , pool(typeCompiler->memoryPool()) , qmlObjects(typeCompiler->qmlObjects()) - , resolvedTypes(&typeCompiler->resolvedTypes) , propertyCaches(std::move(typeCompiler->takePropertyCaches())) { } @@ -803,7 +799,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI continue; const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex); - auto *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex); + auto *tr = resolvedType(targetObject->inheritedTypeNameIndex); Q_ASSERT(tr); const QMetaObject *firstMetaObject = nullptr; @@ -854,12 +850,12 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI syntheticComponent->location = binding->valueLocation; syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent; - if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) { + if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) { auto typeRef = new QV4::CompiledData::ResolvedTypeReference; typeRef->type = componentType; typeRef->majorVersion = componentType.majorVersion(); typeRef->minorVersion = componentType.minorVersion(); - resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef); + insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef); } qmlObjects->append(syntheticComponent); @@ -897,7 +893,7 @@ bool QQmlComponentAndAliasResolver::resolve() bool isExplicitComponent = false; if (obj->inheritedTypeNameIndex) { - auto *tref = resolvedTypes->value(obj->inheritedTypeNameIndex); + auto *tref = resolvedType(obj->inheritedTypeNameIndex); Q_ASSERT(tref); if (tref->type.metaObject() == &QQmlComponent::staticMetaObject) isExplicitComponent = true; @@ -1300,7 +1296,6 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex) QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen) : QQmlCompilePass(typeCompiler) - , resolvedTypes(typeCompiler->resolvedTypes) , customParsers(typeCompiler->customParserCache()) , qmlObjects(*typeCompiler->qmlObjects()) , propertyCaches(typeCompiler->propertyCaches()) @@ -1339,7 +1334,7 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject) m.idIndex = obj->id; m.type = propertyCaches->at(objectIndex); - auto *tref = resolvedTypes.value(obj->inheritedTypeNameIndex); + auto *tref = resolvedType(obj->inheritedTypeNameIndex); if (tref && tref->isFullyDynamicType) m.type = nullptr; -- cgit v1.2.3