From 4578a92744d447222f5e22851433d5dbecc51855 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 4 Sep 2017 18:21:41 +0200 Subject: QmlProfiler: Avoid race conditions in QQmlTypeLoader We have to make sure all profiler calls to one adapter are done from the same thread. It turns out that all the calls from QQmlTypeLoader are done from the type loader thread. By using a separate adapter for that, we avoid any extra locking. Task-number: QTBUG-62987 Change-Id: I5cffcc30b84dd4154daa0c56312a1141ce2033e1 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypeloader.cpp | 14 ++++++++++---- src/qml/qml/qqmltypeloader_p.h | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 84410875ab..9b7b970e56 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -700,8 +700,7 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob) { Q_ASSERT(m_waitingFor.contains(blob)); Q_ASSERT(blob->status() == Error || blob->status() == Complete); - QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, - blob); + QQmlCompilingProfiler prof(typeLoader()->profiler(), blob); m_inCallback = true; @@ -1262,7 +1261,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QString &fileName) void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::SourceCodeData &d) { QML_MEMORY_SCOPE_URL(blob->url()); - QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob); + QQmlCompilingProfiler prof(profiler(), blob); blob->m_inCallback = true; @@ -1282,7 +1281,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::SourceCodeD void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit) { QML_MEMORY_SCOPE_URL(blob->url()); - QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob); + QQmlCompilingProfiler prof(profiler(), blob); blob->m_inCallback = true; @@ -1597,6 +1596,9 @@ Constructs a new type loader that uses the given \a engine. */ QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)), +#ifndef QT_NO_QML_DEBUGGER + m_profiler(nullptr), +#endif m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD) { } @@ -1613,6 +1615,10 @@ QQmlTypeLoader::~QQmlTypeLoader() clearCache(); invalidate(); + +#ifndef QT_NO_QML_DEBUGGER + delete m_profiler; +#endif } QQmlImportDatabase *QQmlTypeLoader::importDatabase() const diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 05923f77e8..722791ea5a 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -84,6 +84,7 @@ class QQmlComponentPrivate; class QQmlTypeData; class QQmlTypeLoader; class QQmlExtensionInterface; +class QQmlProfiler; struct QQmlCompileError; namespace QmlIR { @@ -320,6 +321,15 @@ public: void initializeEngine(QQmlExtensionInterface *, const char *); void invalidate(); +#ifdef QT_NO_QML_DEBUGGER + QQmlProfiler *profiler() const { return nullptr; } + void setProfiler(QQmlProfiler *) {} +#else + QQmlProfiler *profiler() const { return m_profiler; } + void setProfiler(QQmlProfiler *profiler) { Q_ASSERT(!m_profiler); m_profiler = profiler; } +#endif // QT_NO_QML_DEBUGGER + + private: friend class QQmlDataBlob; friend class QQmlTypeLoaderThread; @@ -368,6 +378,11 @@ private: QQmlEngine *m_engine; QQmlTypeLoaderThread *m_thread; + +#ifndef QT_NO_QML_DEBUGGER + QQmlProfiler *m_profiler; +#endif + #if QT_CONFIG(qml_network) NetworkReplies m_networkReplies; #endif -- cgit v1.2.3 From 4dbb3c7bc5829bcf699715157d3a82fb86f4ea5e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 5 Sep 2017 13:24:51 +0200 Subject: Fix QtQml crashing with GHS compiler when using AOT In order to support compilers that do not support the packing attribute, replace the use of the pack macros with static assertions about the structure size, to ensure that what is generated by host tools (qmlcachegen, qqc) is compatible with what's loaded by the target at run-time. This requires padding and re-ordering some structures. Task-number: QTBUG-61468 Change-Id: I3d82457f086a9b066d1c6df4c46d9f154dd5f208 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata_p.h | 43 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 5d71bc4ac6..815c1b92de 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x11 +#define QV4_DATA_STRUCTURE_VERSION 0x12 class QIODevice; class QQmlPropertyCache; @@ -122,10 +122,6 @@ struct TableIterator bool operator!=(const TableIterator &rhs) const { return index != rhs.index; } }; -#if defined(Q_CC_MSVC) || defined(Q_CC_GNU) -#pragma pack(push, 1) -#endif - struct Location { union { @@ -140,6 +136,7 @@ struct Location (line == other.line && column < other.column); } }; +static_assert(sizeof(Location) == 4, "Location structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct RegExp { @@ -155,6 +152,7 @@ struct RegExp RegExp() { flags.val = 0; stringIndex.val = 0; } }; +static_assert(sizeof(RegExp) == 4, "RegExp structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Lookup { @@ -173,6 +171,7 @@ struct Lookup Lookup() { type_and_flags.val = 0; nameIndex.val = 0; } }; +static_assert(sizeof(Lookup) == 4, "Lookup structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct JSClassMember { @@ -183,6 +182,7 @@ struct JSClassMember JSClassMember() { nameOffset = 0; isAccessor = 0; } }; +static_assert(sizeof(JSClassMember) == 4, "JSClassMember structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct JSClass { @@ -191,6 +191,7 @@ struct JSClass static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; } }; +static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct String { @@ -201,6 +202,7 @@ struct String return (sizeof(String) + str.length() * sizeof(quint16) + 7) & ~0x7; } }; +static_assert(sizeof(String) == 4, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); // Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties // for unaligned access. The ordering of the fields is also from largest to smallest. @@ -243,6 +245,8 @@ struct Function // Keep all unaligned data at the end quint8 flags; + quint8 padding1; + LEUInt16 padding2; const LEUInt32 *formalsTable() const { return reinterpret_cast(reinterpret_cast(this) + formalsOffset); } const LEUInt32 *localsTable() const { return reinterpret_cast(reinterpret_cast(this) + localsOffset); } @@ -261,6 +265,7 @@ struct Function return (sizeof(Function) + (nFormals + nLocals + nInnerfunctions + nIdObjectDependencies + 2 * nPropertyDependencies) * sizeof(quint32) + 7) & ~0x7; } }; +static_assert(sizeof(Function) == 72, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); // Qml data structures @@ -268,6 +273,7 @@ struct Q_QML_EXPORT TranslationData { LEUInt32 commentIndex; LEInt32 number; }; +static_assert(sizeof(TranslationData) == 8, "TranslationData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Q_QML_PRIVATE_EXPORT Binding { @@ -298,10 +304,7 @@ struct Q_QML_PRIVATE_EXPORT Binding IsCustomParserBinding = 0x100, }; - union { - QJsonPrivate::qle_bitfield<0, 16> flags; - QJsonPrivate::qle_bitfield<16, 16> type; - }; + LEUInt32 stringIndex; // Set for Type_String, Type_Translation and Type_Script (the latter because of script strings) union { bool b; quint64 doubleValue; // do not access directly, needs endian protected access @@ -309,11 +312,17 @@ struct Q_QML_PRIVATE_EXPORT Binding LEUInt32 objectIndex; TranslationData translationData; // used when Type_Translation } value; - LEUInt32 stringIndex; // Set for Type_String, Type_Translation and Type_Script (the latter because of script strings) + + union { + QJsonPrivate::qle_bitfield<0, 16> flags; + QJsonPrivate::qle_bitfield<16, 16> type; + }; Location location; Location valueLocation; + LEUInt32 padding; + bool isValueBinding() const { if (type == Type_AttachedProperty @@ -392,6 +401,8 @@ struct Q_QML_PRIVATE_EXPORT Binding }; +static_assert(sizeof(Binding) == 32, "Binding structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); + struct Parameter { LEUInt32 nameIndex; @@ -399,6 +410,7 @@ struct Parameter LEUInt32 customTypeNameIndex; Location location; }; +static_assert(sizeof(Parameter) == 16, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Signal { @@ -423,6 +435,7 @@ struct Signal int parameterCount() const { return nParameters; } // --- }; +static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Property { @@ -443,6 +456,7 @@ struct Property LEUInt32 customTypeNameIndex; // If type >= Custom Location location; }; +static_assert(sizeof(Property) == 16, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Alias { enum Flags : unsigned int { @@ -472,6 +486,7 @@ struct Alias { return encodedMetaPropertyIndex == -1; } }; +static_assert(sizeof(Alias) == 20, "Alias structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Object { @@ -579,6 +594,7 @@ struct Object int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; } // --- }; +static_assert(sizeof(Object) == 72, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Import { @@ -599,6 +615,7 @@ struct Import Import() { type = 0; uriIndex = 0; qualifierIndex = 0; majorVersion = 0; minorVersion = 0; } }; +static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); static const char magic_str[] = "qv4cdata"; @@ -651,6 +668,8 @@ struct Unit LEUInt32 offsetToObjects; LEUInt32 indexOfRootObject; + LEUInt32 padding; + const Import *importAt(int idx) const { return reinterpret_cast((reinterpret_cast(this)) + offsetToImports + idx * sizeof(Import)); } @@ -715,9 +734,7 @@ struct Unit } }; -#if defined(Q_CC_MSVC) || defined(Q_CC_GNU) -#pragma pack(pop) -#endif +static_assert(sizeof(Unit) == 152, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct TypeReference { -- cgit v1.2.3 From a88ca874970c57db275981a1a47a0bebb6b749a0 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 5 Sep 2017 15:23:05 +0200 Subject: Qml Tooling: Replace bare pointers with QScopedPointer This way we don't have to manually initialize and delete them. Change-Id: I0104c744dba380e957271d0924498e3643856e9e Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 14 ++------------ src/qml/jsruntime/qv4engine_p.h | 8 ++++---- src/qml/qml/qqmltypeloader.cpp | 15 ++++++++------- src/qml/qml/qqmltypeloader_p.h | 8 ++++---- 4 files changed, 18 insertions(+), 27 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 0c4facda4d..5e776ea09b 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -141,10 +141,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) , m_engineId(engineSerial.fetchAndAddOrdered(1)) , regExpCache(0) , m_multiplyWrappedQObjects(0) -#ifndef QT_NO_QML_DEBUGGER - , m_debugger(0) - , m_profiler(0) -#endif { memoryManager = new QV4::MemoryManager(this); @@ -477,12 +473,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) ExecutionEngine::~ExecutionEngine() { -#ifndef QT_NO_QML_DEBUGGER - delete m_debugger; - m_debugger = 0; - delete m_profiler; - m_profiler = 0; -#endif delete m_multiplyWrappedQObjects; m_multiplyWrappedQObjects = 0; delete identifierTable; @@ -508,13 +498,13 @@ ExecutionEngine::~ExecutionEngine() void ExecutionEngine::setDebugger(Debugging::Debugger *debugger) { Q_ASSERT(!m_debugger); - m_debugger = debugger; + m_debugger.reset(debugger); } void ExecutionEngine::setProfiler(Profiling::Profiler *profiler) { Q_ASSERT(!m_profiler); - m_profiler = profiler; + m_profiler.reset(profiler); } #endif // QT_NO_QML_DEBUGGER diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index a569b8ddf9..d331fd7bff 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -353,8 +353,8 @@ public: void setDebugger(Debugging::Debugger *) {} void setProfiler(Profiling::Profiler *) {} #else - QV4::Debugging::Debugger *debugger() const { return m_debugger; } - QV4::Profiling::Profiler *profiler() const { return m_profiler; } + QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); } + QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); } void setDebugger(Debugging::Debugger *debugger); void setProfiler(Profiling::Profiler *profiler); @@ -464,8 +464,8 @@ private: void failStackLimitCheck(Scope &scope); #ifndef QT_NO_QML_DEBUGGER - QV4::Debugging::Debugger *m_debugger; - QV4::Profiling::Profiler *m_profiler; + QScopedPointer m_debugger; + QScopedPointer m_profiler; #endif }; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 9b7b970e56..ce795be757 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -962,6 +962,14 @@ void QQmlTypeLoader::invalidate() #endif // qml_network } +#ifndef QT_NO_QML_DEBUGGER +void QQmlTypeLoader::setProfiler(QQmlProfiler *profiler) +{ + Q_ASSERT(!m_profiler); + m_profiler.reset(profiler); +} +#endif + void QQmlTypeLoader::lock() { m_thread->lock(); @@ -1596,9 +1604,6 @@ Constructs a new type loader that uses the given \a engine. */ QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)), -#ifndef QT_NO_QML_DEBUGGER - m_profiler(nullptr), -#endif m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD) { } @@ -1615,10 +1620,6 @@ QQmlTypeLoader::~QQmlTypeLoader() clearCache(); invalidate(); - -#ifndef QT_NO_QML_DEBUGGER - delete m_profiler; -#endif } QQmlImportDatabase *QQmlTypeLoader::importDatabase() const diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 722791ea5a..c214f0cd43 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -249,7 +249,7 @@ private: QString m_location; }; -class Q_AUTOTEST_EXPORT QQmlTypeLoader +class Q_QML_PRIVATE_EXPORT QQmlTypeLoader { Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader) public: @@ -325,8 +325,8 @@ public: QQmlProfiler *profiler() const { return nullptr; } void setProfiler(QQmlProfiler *) {} #else - QQmlProfiler *profiler() const { return m_profiler; } - void setProfiler(QQmlProfiler *profiler) { Q_ASSERT(!m_profiler); m_profiler = profiler; } + QQmlProfiler *profiler() const { return m_profiler.data(); } + void setProfiler(QQmlProfiler *profiler); #endif // QT_NO_QML_DEBUGGER @@ -380,7 +380,7 @@ private: QQmlTypeLoaderThread *m_thread; #ifndef QT_NO_QML_DEBUGGER - QQmlProfiler *m_profiler; + QScopedPointer m_profiler; #endif #if QT_CONFIG(qml_network) -- cgit v1.2.3 From e22b624d9ab1f36021adb9cdbfa9b37054282bb8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 14 Aug 2017 16:29:46 +0200 Subject: Fix crashes with closures created in QML components When closures created inside QML components are called after the surrounding component (and consequently QML context) has been destroyed, we are in a somewhat limited environment. Initially we would just crash as the calling QML context is not valid anymore. We can alleviate that by introducing reference counting on the context and letting the QML context wrapper keep a strong reference. This avoids the crashes and also ensures that at least imports continue to be accessible within these contexts (as the singleton test case demonstrates). Task-number: QTBUG-61781 Change-Id: I893f171842d01b0863d95a02ea738adc2620e236 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4qmlcontext.cpp | 9 +-- src/qml/jsruntime/qv4qmlcontext_p.h | 13 +--- src/qml/jsruntime/qv4qobjectwrapper.cpp | 8 +- src/qml/qml/qqmlcontext.cpp | 59 +++++++++----- src/qml/qml/qqmlcontext_p.h | 132 +++++++++++++++++++++----------- src/qml/qml/qqmldata_p.h | 36 ++++++++- src/qml/qml/qqmlengine.cpp | 20 +++-- src/qml/qml/qqmlobjectcreator.cpp | 2 +- src/qml/qml/qqmltypeloader.cpp | 6 +- src/qml/qml/qqmlxmlhttprequest.cpp | 2 +- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 4 + src/qml/types/qqmldelegatemodel.cpp | 23 ++++-- src/qml/types/qqmldelegatemodel_p_p.h | 2 +- 13 files changed, 210 insertions(+), 106 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 144ab1b1a5..d97d44379d 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -62,20 +62,17 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlContextWrapper); DEFINE_MANAGED_VTABLE(QmlContext); -void Heap::QmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject, bool ownsContext) +void Heap::QmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject) { Object::init(); readOnly = true; - this->ownsContext = ownsContext; isNullWrapper = false; - this->context = new QQmlGuardedContextData(context); + this->context = new QQmlContextDataRef(context); this->scopeObject.init(scopeObject); } void Heap::QmlContextWrapper::destroy() { - if (*context && ownsContext) - (*context)->destroy(); delete context; scopeObject.destroy(); Object::destroy(); @@ -321,7 +318,7 @@ Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, cons context->isInternal = true; context->isJSContext = true; - Scoped qml(scope, scope.engine->memoryManager->allocObject(context, (QObject*)0, true)); + Scoped qml(scope, scope.engine->memoryManager->allocObject(context, (QObject*)0)); qml->d()->isNullWrapper = true; qml->setReadOnly(false); diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h index 9aec7467da..9caeb75b8c 100644 --- a/src/qml/jsruntime/qv4qmlcontext_p.h +++ b/src/qml/jsruntime/qv4qmlcontext_p.h @@ -67,13 +67,12 @@ struct QmlContextWrapper; namespace Heap { struct QmlContextWrapper : Object { - void init(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); + void init(QQmlContextData *context, QObject *scopeObject); void destroy(); bool readOnly; - bool ownsContext; bool isNullWrapper; - QQmlGuardedContextData *context; + QQmlContextDataRef *context; QQmlQPointer scopeObject; }; @@ -90,10 +89,6 @@ struct Q_QML_EXPORT QmlContextWrapper : Object V4_OBJECT2(QmlContextWrapper, Object) V4_NEEDS_DESTROY - void takeContextOwnership() { - d()->ownsContext = true; - } - inline QObject *getScopeObject() const { return d()->scopeObject; } inline QQmlContextData *getContext() const { return *d()->context; } @@ -116,10 +111,6 @@ struct Q_QML_EXPORT QmlContext : public ExecutionContext QQmlContextData *qmlContext() const { return *d()->qml->context; } - - void takeContextOwnership() { - d()->qml->ownsContext = true; - } }; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 5dc5f5d568..8d96f5b480 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -977,8 +977,12 @@ void QObjectWrapper::destroyObject(bool lastCall) QQmlData *ddata = QQmlData::get(h->object(), false); if (ddata) { if (!h->object()->parent() && !ddata->indestructible) { - if (ddata && ddata->ownContext && ddata->context) - ddata->context->emitDestruction(); + if (ddata && ddata->ownContext) { + Q_ASSERT(ddata->ownContext == ddata->context); + ddata->ownContext->emitDestruction(); + ddata->ownContext = 0; + ddata->context = 0; + } // This object is notionally destroyed now ddata->isQueuedForDeletion = true; if (lastCall) diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 531d9ae457..e06491a814 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -161,6 +161,7 @@ QQmlContext::QQmlContext(QQmlEngine *e, bool) { Q_D(QQmlContext); d->data = new QQmlContextData(this); + ++d->data->refCount; d->data->engine = e; } @@ -174,6 +175,7 @@ QQmlContext::QQmlContext(QQmlEngine *engine, QObject *parent) { Q_D(QQmlContext); d->data = new QQmlContextData(this); + ++d->data->refCount; d->data->setParent(engine?QQmlContextData::get(engine->rootContext()):0); } @@ -187,6 +189,7 @@ QQmlContext::QQmlContext(QQmlContext *parentContext, QObject *parent) { Q_D(QQmlContext); d->data = new QQmlContextData(this); + ++d->data->refCount; d->data->setParent(parentContext?QQmlContextData::get(parentContext):0); } @@ -199,6 +202,7 @@ QQmlContext::QQmlContext(QQmlContextData *data) { Q_D(QQmlContext); d->data = data; + // don't add a refcount here, as the data owns this context } /*! @@ -212,7 +216,8 @@ QQmlContext::~QQmlContext() { Q_D(QQmlContext); - if (!d->data->isInternal) + d->data->publicContext = 0; + if (!--d->data->refCount) d->data->destroy(); } @@ -521,12 +526,12 @@ QQmlContextData::QQmlContextData() } QQmlContextData::QQmlContextData(QQmlContext *ctxt) -: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), - isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false), - publicContext(ctxt), incubator(0), componentObjectIndex(-1), - contextObject(0), childContexts(0), nextChild(0), prevChild(0), - expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0), - componentAttached(0) + : engine(0), isInternal(false), isJSContext(false), + isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false), + publicContext(ctxt), incubator(0), componentObjectIndex(-1), + contextObject(0), nextChild(0), prevChild(0), + expressions(0), contextObjects(0), idValues(0), idValueCount(0), + componentAttached(0) { } @@ -563,11 +568,8 @@ void QQmlContextData::invalidate() emitDestruction(); while (childContexts) { - if (childContexts->ownedByParent) { - childContexts->destroy(); - } else { - childContexts->invalidate(); - } + Q_ASSERT(childContexts != this); + childContexts->invalidate(); } if (prevChild) { @@ -601,12 +603,17 @@ void QQmlContextData::clearContext() void QQmlContextData::destroy() { - if (linkedContext) - linkedContext->destroy(); + Q_ASSERT(refCount == 0); + linkedContext = 0; - if (engine) invalidate(); + // avoid recursion + ++refCount; + if (engine) + invalidate(); + Q_ASSERT(refCount == 1); clearContext(); + Q_ASSERT(refCount == 1); while (contextObjects) { QQmlData *co = contextObjects; @@ -617,6 +624,7 @@ void QQmlContextData::destroy() co->nextContextObject = 0; co->prevContextObject = 0; } + Q_ASSERT(refCount == 1); QQmlGuardedContextData *contextGuard = contextGuards; while (contextGuard) { @@ -627,17 +635,29 @@ void QQmlContextData::destroy() contextGuard = next; } contextGuards = 0; + Q_ASSERT(refCount == 1); delete [] idValues; + idValues = 0; - if (isInternal) + Q_ASSERT(refCount == 1); + if (publicContext) { + // the QQmlContext destructor will remove one ref again + ++refCount; delete publicContext; + } + + Q_ASSERT(refCount == 1); + --refCount; + Q_ASSERT(refCount == 0); delete this; } -void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership) +void QQmlContextData::setParent(QQmlContextData *p) { + if (p == parent) + return; if (p) { parent = p; engine = p->engine; @@ -645,7 +665,6 @@ void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership) if (nextChild) nextChild->prevChild = &nextChild; prevChild = &p->childContexts; p->childContexts = this; - ownedByParent = parentTakesOwnership; } } @@ -660,6 +679,10 @@ void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expr expression->refresh(); } +QQmlContextData::~QQmlContextData() +{ +} + static inline bool expressions_to_run(QQmlContextData *ctxt, bool isGlobalRefresh) { return ctxt->expressions && (!isGlobalRefresh || ctxt->unresolvedNames); diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index a259fd62d8..d01820a430 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -78,6 +78,7 @@ class QQmlExpression; class QQmlExpressionPrivate; class QQmlJavaScriptExpression; class QQmlContextData; +class QQmlGuardedContextData; class QQmlIncubatorPrivate; class QQmlContextPrivate : public QObjectPrivate @@ -106,7 +107,7 @@ public: }; class QQmlComponentAttached; -class QQmlGuardedContextData; + class Q_QML_PRIVATE_EXPORT QQmlContextData { public: @@ -114,7 +115,6 @@ public: QQmlContextData(QQmlContext *); void emitDestruction(); void clearContext(); - void destroy(); void invalidate(); inline bool isValid() const { @@ -122,10 +122,10 @@ public: } // My parent context and engine - QQmlContextData *parent; + QQmlContextData *parent = nullptr; QQmlEngine *engine; - void setParent(QQmlContextData *, bool parentTakesOwnership = false); + void setParent(QQmlContextData *); void refreshExpressions(); void addObject(QObject *); @@ -136,14 +136,14 @@ public: // If internal is false publicContext owns this. QQmlContext *asQQmlContext(); QQmlContextPrivate *asQQmlContextPrivate(); + quint32 refCount = 0; quint32 isInternal:1; - quint32 ownedByParent:1; // unrelated to isInternal; parent context deletes children if true. quint32 isJSContext:1; quint32 isPragmaLibraryContext:1; quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name quint32 hasEmittedDestruction:1; quint32 isRootObjectInCreation:1; - quint32 dummy:25; + quint32 dummy:26; QQmlContext *publicContext; // The incubator that is constructing this context if any @@ -178,7 +178,7 @@ public: QQmlRefPointer imports; // My children - QQmlContextData *childContexts; + QQmlContextData *childContexts = 0; // My peers in parent's childContexts list QQmlContextData *nextChild; @@ -191,7 +191,7 @@ public: QQmlData *contextObjects; // Doubly-linked list of context guards (XXX merge with contextObjects) - QQmlGuardedContextData *contextGuards; + QQmlGuardedContextData *contextGuards = 0; // id guards struct ContextGuard : public QQmlGuard @@ -210,7 +210,7 @@ public: void setIdProperty(int, QObject *); // Linked contexts. this owns linkedContext. - QQmlContextData *linkedContext; + QQmlContextDataRef linkedContext; // Linked list of uses of the Component attached property in this // context @@ -224,91 +224,137 @@ public: } private: + friend class QQmlContextDataRef; + friend class QQmlContext; // needs to do manual refcounting :/ void refreshExpressionsRecursive(bool isGlobal); void refreshExpressionsRecursive(QQmlJavaScriptExpression *); - ~QQmlContextData() {} + ~QQmlContextData(); + void destroy(); }; + class QQmlGuardedContextData { public: - inline QQmlGuardedContextData(); - inline QQmlGuardedContextData(QQmlContextData *); - inline ~QQmlGuardedContextData(); - - inline QQmlContextData *contextData() const; + inline QQmlGuardedContextData() = default; + inline QQmlGuardedContextData(QQmlContextData *data) + { setContextData(data); } + inline ~QQmlGuardedContextData() + { clear(); } + + inline QQmlContextData *contextData() const + { return m_contextData; } inline void setContextData(QQmlContextData *); inline bool isNull() const { return !m_contextData; } inline operator QQmlContextData*() const { return m_contextData; } inline QQmlContextData* operator->() const { return m_contextData; } - inline QQmlGuardedContextData &operator=(QQmlContextData *d); + inline QQmlGuardedContextData &operator=(QQmlContextData *d) { + setContextData(d); return *this; + } private: - QQmlGuardedContextData &operator=(const QQmlGuardedContextData &); - QQmlGuardedContextData(const QQmlGuardedContextData &); + QQmlGuardedContextData &operator=(const QQmlGuardedContextData &) = delete; + QQmlGuardedContextData(const QQmlGuardedContextData &) = delete; friend class QQmlContextData; inline void clear(); - QQmlContextData *m_contextData; - QQmlGuardedContextData *m_next; - QQmlGuardedContextData **m_prev; + QQmlContextData *m_contextData = 0; + QQmlGuardedContextData *m_next = 0; + QQmlGuardedContextData **m_prev = 0; }; -QQmlGuardedContextData::QQmlGuardedContextData() -: m_contextData(0), m_next(0), m_prev(0) + +void QQmlGuardedContextData::setContextData(QQmlContextData *contextData) + { + if (m_contextData == contextData) + return; + clear(); + + if (contextData) { + m_contextData = contextData; + m_next = contextData->contextGuards; + if (m_next) m_next->m_prev = &m_next; + m_prev = &contextData->contextGuards; + contextData->contextGuards = this; + } +} + +void QQmlGuardedContextData::clear() +{ + if (m_prev) { + *m_prev = m_next; + if (m_next) m_next->m_prev = m_prev; + m_contextData = 0; + m_next = 0; + m_prev = 0; + } +} + +QQmlContextDataRef::QQmlContextDataRef() + : m_contextData(0) { } -QQmlGuardedContextData::QQmlGuardedContextData(QQmlContextData *data) -: m_contextData(0), m_next(0), m_prev(0) +QQmlContextDataRef::QQmlContextDataRef(const QQmlContextDataRef &other) + : m_contextData(other.m_contextData) { - setContextData(data); + if (m_contextData) + ++m_contextData->refCount; } -QQmlGuardedContextData::~QQmlGuardedContextData() +QQmlContextDataRef::QQmlContextDataRef(QQmlContextData *data) + : m_contextData(data) +{ + if (m_contextData) + ++m_contextData->refCount; +} + +QQmlContextDataRef::~QQmlContextDataRef() { clear(); } -void QQmlGuardedContextData::setContextData(QQmlContextData *contextData) +void QQmlContextDataRef::setContextData(QQmlContextData *contextData) { + if (m_contextData == contextData) + return; clear(); if (contextData) { m_contextData = contextData; - m_next = contextData->contextGuards; - if (m_next) m_next->m_prev = &m_next; - m_prev = &contextData->contextGuards; - contextData->contextGuards = this; + ++m_contextData->refCount; } } -QQmlContextData *QQmlGuardedContextData::contextData() const +QQmlContextData *QQmlContextDataRef::contextData() const { return m_contextData; } -void QQmlGuardedContextData::clear() +void QQmlContextDataRef::clear() { - if (m_prev) { - *m_prev = m_next; - if (m_next) m_next->m_prev = m_prev; - m_contextData = 0; - m_next = 0; - m_prev = 0; - } + if (m_contextData && !--m_contextData->refCount) + m_contextData->destroy(); + m_contextData = 0; } -QQmlGuardedContextData & -QQmlGuardedContextData::operator=(QQmlContextData *d) +QQmlContextDataRef & +QQmlContextDataRef::operator=(QQmlContextData *d) { setContextData(d); return *this; } +QQmlContextDataRef & +QQmlContextDataRef::operator=(const QQmlContextDataRef &other) +{ + setContextData(other.m_contextData); + return *this; +} + QQmlContextData::ContextGuard::ContextGuard() : context(0) { diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 2083326cd5..75ea720358 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -78,6 +78,34 @@ struct CompilationUnit; } } +// This is declared here because QQmlData below needs it and this file +// in turn is included from qqmlcontext_p.h. +class QQmlContextData; +class Q_QML_PRIVATE_EXPORT QQmlContextDataRef +{ +public: + inline QQmlContextDataRef(); + inline QQmlContextDataRef(QQmlContextData *); + inline QQmlContextDataRef(const QQmlContextDataRef &); + inline ~QQmlContextDataRef(); + + inline QQmlContextData *contextData() const; + inline void setContextData(QQmlContextData *); + + inline bool isNull() const { return !m_contextData; } + + inline operator QQmlContextData*() const { return m_contextData; } + inline QQmlContextData* operator->() const { return m_contextData; } + inline QQmlContextDataRef &operator=(QQmlContextData *d); + inline QQmlContextDataRef &operator=(const QQmlContextDataRef &other); + +private: + + inline void clear(); + + QQmlContextData *m_contextData; +}; + // This class is structured in such a way, that simply zero'ing it is the // default state for elemental object allocations. This is crucial in the // workings of the QQmlInstruction::CreateSimpleObject instruction. @@ -114,7 +142,6 @@ public: quint32 ownedByQml1:1; // This bit is shared with QML1's QDeclarativeData. quint32 ownMemory:1; - quint32 ownContext:1; quint32 indestructible:1; quint32 explicitIndestructibleSet:1; quint32 hasTaintedV4Object:1; @@ -127,7 +154,7 @@ public: quint32 hasInterceptorMetaObject:1; quint32 hasVMEMetaObject:1; quint32 parentFrozen:1; - quint32 dummy:21; + quint32 dummy:22; // When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside // bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated @@ -161,9 +188,10 @@ public: void disconnectNotifiers(); // The context that created the C++ object - QQmlContextData *context; + QQmlContextData *context = 0; // The outermost context in which this object lives - QQmlContextData *outerContext; + QQmlContextData *outerContext = 0; + QQmlContextDataRef ownContext; QQmlAbstractBinding *bindings; QQmlBoundSignal *signalHandlers; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 9676feb279..f31db457d3 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -712,8 +712,11 @@ QQmlEnginePrivate::~QQmlEnginePrivate() void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) { if (QQmlData *d = QQmlData::get(o)) { - if (d->ownContext && d->context) { - d->context->destroy(); + if (d->ownContext) { + for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext) + lc->invalidate(); + d->ownContext->invalidate(); + d->ownContext = 0; d->context = 0; } @@ -729,10 +732,10 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) } QQmlData::QQmlData() - : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), + : ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false), hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), - bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0), context(0), outerContext(0), + bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0), bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0), deferredData(0), propertyCache(0), guards(0), extendedData(0) @@ -882,8 +885,12 @@ void QQmlData::setQueuedForDeletion(QObject *object) { if (object) { if (QQmlData *ddata = QQmlData::get(object)) { - if (ddata->ownContext && ddata->context) + if (ddata->ownContext) { + Q_ASSERT(ddata->ownContext == ddata->context); ddata->context->emitDestruction(); + ddata->ownContext = 0; + ddata->context = 0; + } ddata->isQueuedForDeletion = true; } } @@ -1753,8 +1760,7 @@ void QQmlData::destroyed(QObject *object) if (propertyCache) propertyCache->release(); - if (ownContext && context) - context->destroy(); + ownContext = 0; while (guards) { QQmlGuard *guard = static_cast *>(guards); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index b34c2ea5e6..890d1ca7fe 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1131,7 +1131,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo c->linkedContext = context; } else context->addObject(instance); - ddata->ownContext = true; + ddata->ownContext = ddata->context; } else if (!ddata->context) context->addObject(instance); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index ce795be757..342e6c0725 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2817,7 +2817,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent effectiveCtxt = 0; // Create the script context if required - QQmlContextData *ctxt = new QQmlContextData; + QQmlContextDataRef ctxt(new QQmlContextData); ctxt->isInternal = true; ctxt->isJSContext = true; if (shared) @@ -2837,7 +2837,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent } if (effectiveCtxt) { - ctxt->setParent(effectiveCtxt, true); + ctxt->setParent(effectiveCtxt); } else { ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620 } @@ -2859,12 +2859,10 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent if (!m_program) { if (shared) m_loaded = true; - ctxt->destroy(); return QV4::Encode::undefined(); } QV4::Scoped qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxt, 0)); - qmlContext->takeContextOwnership(); m_program->qmlContext.set(scope.engine, qmlContext); m_program->run(); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index f3a39313c1..58d8322675 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1058,7 +1058,7 @@ private: void readEncoding(); PersistentValue m_thisObject; - QQmlGuardedContextData m_qmlContext; + QQmlContextDataRef m_qmlContext; static void dispatchCallback(Object *thisObj, QQmlContextData *context); void dispatchCallback(); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 8cc0b32168..96d83b9870 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1150,6 +1150,10 @@ void QtObject::method_createQmlObject(const BuiltinFunction *, Scope &scope, Cal if (!component.isReady()) THROW_GENERIC_ERROR("Qt.createQmlObject(): Component is not ready"); + if (!effectiveContext->isValid()) { + THROW_GENERIC_ERROR("Qt.createQmlObject(): Cannot create a component in an invalid context"); + } + QObject *obj = component.beginCreate(effectiveContext); if (obj) { QQmlData::get(obj, true)->explicitIndestructibleSet = false; diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 6584ecfb84..9b1417eccd 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -269,7 +269,8 @@ QQmlDelegateModel::~QQmlDelegateModel() delete cacheItem->object; cacheItem->object = 0; - cacheItem->contextData->destroy(); + cacheItem->contextData->invalidate(); + Q_ASSERT(cacheItem->contextData->refCount == 1); cacheItem->contextData = 0; cacheItem->scriptRef -= 1; } @@ -840,7 +841,8 @@ void QQDMIncubationTask::statusChanged(Status status) delete incubating->object; incubating->object = 0; if (incubating->contextData) { - incubating->contextData->destroy(); + incubating->contextData->invalidate(); + Q_ASSERT(incubating->contextData->refCount == 1); incubating->contextData = 0; } incubating->scriptRef = 0; @@ -900,8 +902,10 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba delete cacheItem->object; cacheItem->object = 0; cacheItem->scriptRef -= 1; - if (cacheItem->contextData) - cacheItem->contextData->destroy(); + if (cacheItem->contextData) { + cacheItem->contextData->invalidate(); + Q_ASSERT(cacheItem->contextData->refCount == 1); + } cacheItem->contextData = 0; if (!cacheItem->isReferenced()) { @@ -983,7 +987,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo if (QQmlAdaptorModelProxyInterface *proxy = qobject_cast(cacheItem)) { ctxt = new QQmlContextData; - ctxt->setParent(cacheItem->contextData, true); + ctxt->setParent(cacheItem->contextData); ctxt->contextObject = proxy->proxiedObject(); } } @@ -1966,8 +1970,11 @@ void QQmlDelegateModelItem::destroyObject() QQmlData *data = QQmlData::get(object); Q_ASSERT(data); - if (data->ownContext && data->context) - data->context->clearContext(); + if (data->ownContext) { + data->ownContext->clearContext(); + data->ownContext = 0; + data->context = 0; + } object->deleteLater(); if (attached) { @@ -1975,7 +1982,7 @@ void QQmlDelegateModelItem::destroyObject() attached = 0; } - contextData->destroy(); + contextData->invalidate(); contextData = 0; object = 0; } diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index cb4a1f79ba..0f8438870a 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -140,7 +140,7 @@ public: QV4::ExecutionEngine *v4; QQmlDelegateModelItemMetaType * const metaType; - QQmlContextData *contextData; + QQmlContextDataRef contextData; QPointer object; QPointer attached; QQDMIncubationTask *incubationTask; -- 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') 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 161159bfec511112daa7ad0fe1d2375edbf41401 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 7 Sep 2017 10:15:49 +0200 Subject: QQmlPropertyValidator::validateObject(): remove unused code This code was moved to QQmlDeferredBindingScanner in f27d058. Change-Id: I8cf261c497ec433a14e00e17b67a284b45cf8d75 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlpropertyvalidator.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 4ac7aad553..6929318c59 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -94,16 +94,6 @@ QVector QQmlPropertyValidator::validateObject(int objectIndex, if (!propertyCache) return QVector(); - QStringList deferredPropertyNames; - { - const QMetaObject *mo = propertyCache->firstCppMetaObject(); - const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames"); - if (namesIndex != -1) { - QMetaClassInfo classInfo = mo->classInfo(namesIndex); - deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(',')); - } - } - QQmlCustomParser *customParser = 0; if (auto typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { if (typeRef->type.isValid()) -- cgit v1.2.3 From aff417321d0aad5da462a63b103b82bc19809841 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 Sep 2017 13:02:57 +0200 Subject: Fix crashes in QML apps when upgrading Qt snapshots When upgrading from one Qt snapshot to another, we may not end up bumping the Qt version. However we do need to re-generate QML cache files. Therefore let's encode the commit hash of declarative in the checksums. Task-number: QTBUG-62302 Change-Id: Ia597fcbe05ea2d32664da2572a1b35c624490095 Reviewed-by: Joerg Bornemann --- src/qml/compiler/qv4compileddata.cpp | 16 ++++++---------- src/qml/qml.pro | 13 +++++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 32e8ee4da2..6702966d11 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -731,8 +731,6 @@ void ResolvedTypeReference::doDynamicTypeCheck() isFullyDynamicType = qtTypeInherits(mo); } -#if defined(QT_BUILD_INTERNAL) - static QByteArray ownLibraryChecksum() { static QByteArray libraryChecksum; @@ -740,7 +738,10 @@ static QByteArray ownLibraryChecksum() if (checksumInitialized) return libraryChecksum; checksumInitialized = true; -#if !defined(QT_NO_DYNAMIC_CAST) && QT_CONFIG(dlopen) +#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_DYNAMIC_CAST) && QT_CONFIG(dlopen) + // This is a bit of a hack to make development easier. When hacking on the code generator + // the cache files may end up being re-used. To avoid that we also add the checksum of + // the QtQml library. Dl_info libInfo; if (dladdr(reinterpret_cast(&ownLibraryChecksum), &libInfo) != 0) { QFile library(QFile::decodeName(libInfo.dli_fname)); @@ -750,14 +751,14 @@ static QByteArray ownLibraryChecksum() libraryChecksum = hash.result(); } } +#elif defined(QML_COMPILE_HASH) + libraryChecksum = QByteArray(QT_STRINGIFY(QML_COMPILE_HASH)); #else // Not implemented. #endif return libraryChecksum; } -#endif - bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const { for (auto it = constBegin(), end = constEnd(); it != end; ++it) { @@ -765,12 +766,7 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *e return false; } - // This is a bit of a hack to make development easier. When hacking on the code generator - // the cache files may end up being re-used. To avoid that we also add the checksum of - // the QtQml library. -#if defined(QT_BUILD_INTERNAL) hash->addData(ownLibraryChecksum()); -#endif return true; } diff --git a/src/qml/qml.pro b/src/qml/qml.pro index be3956bb61..e9d7dcbd2d 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -16,6 +16,19 @@ gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks DEFINES += QT_NO_FOREACH +tagFile=$$PWD/../../.tag +tag= +exists($$tagFile) { + tag=$$cat($$tagFile, singleline) + QMAKE_INTERNAL_INCLUDED_FILES += $$tagFile +} +!equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") { + DEFINES += QML_COMPILE_HASH="$$tag" +} else:exists($$PWD/../../.git) { + commit=$$system(git describe --tags --always --long --dirty) + DEFINES += QML_COMPILE_HASH="$$commit" +} + exists("qqml_enable_gcov") { QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors LIBS_PRIVATE += -lgcov -- cgit v1.2.3 From 286d72e458c10bae3ce11c58a16352a53ba06aef Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 Sep 2017 12:15:31 +0200 Subject: Fix crash with dangling context object pointers This is a regression introduced by commit e22b624d9ab1f36021adb9cdbfa9b37054282bb8, where the object that owns the QML context would destroy the context upon struction. Now the context may live longer and thus the context->contextObject pointer would become a dangling pointer. Task-number: QTBUG-63078 Change-Id: I8fdab4086b0472d5d4930cf57aa76922b7ed9e2e Reviewed-by: Lars Knoll --- src/qml/qml/qqmlengine.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index f31db457d3..13b17e6946 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -716,6 +716,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext) lc->invalidate(); d->ownContext->invalidate(); + if (d->ownContext->contextObject == o) + d->ownContext->contextObject = nullptr; d->ownContext = 0; d->context = 0; } -- cgit v1.2.3 From 874539649508cc1a9cd0ec7ab45b374d18c2c4e5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 Sep 2017 09:43:21 +0200 Subject: Fix crash with loading cache files originating from top-level components If a .qml file starts with Component {} and its item(s) define their own properties, alias, etc. then loading this file initially would work, but loading it from a cache file would crash with dangling pointers in the property cache. This was due to us registering aliases, properties, etc. twice in the property cache, exceeding the reservation in the property cache vectors. The minimal fix is to skip the root object in the property cache creating loop as we do handle it separately afterwards. It needs to be separate because the first object index within the component does not stem from a binding. However as the root object index is always zero, I'll make a follow-up patch to get rid of of the variable. Task-number: QTBUG-62263 Change-Id: I86b76d38cb490750a561eac2b0ad6fff6ef2e20a Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlpropertycachecreator_p.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/qml') diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 8fc8943366..2dd2e82651 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -562,6 +562,8 @@ template inline void QQmlPropertyCacheAliasCreator::appendAliasPropertiesToMetaObjects() { for (int i = 0; i < objectContainer->objectCount(); ++i) { + if (i == objectContainer->rootObjectIndex()) + continue; const CompiledObject &component = *objectContainer->objectAt(i); if (!(component.flags & QV4::CompiledData::Object::IsComponent)) continue; -- 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/qqmlirbuilder.cpp | 9 ++++----- src/qml/compiler/qqmlirbuilder_p.h | 1 - src/qml/compiler/qqmlpropertycachecreator_p.h | 14 +++++++------- src/qml/compiler/qqmlpropertyvalidator.cpp | 2 +- src/qml/compiler/qqmltypecompiler.cpp | 26 ++++++++++---------------- src/qml/compiler/qqmltypecompiler_p.h | 2 -- src/qml/compiler/qv4compileddata.cpp | 6 +++--- src/qml/compiler/qv4compileddata_p.h | 6 ++---- src/qml/compiler/qv4compiler.cpp | 1 - src/qml/qml/qqmlcontext.cpp | 2 +- src/qml/qml/qqmlobjectcreator.cpp | 4 ++-- 11 files changed, 30 insertions(+), 43 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 8db054c91f..092c0020fa 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -300,7 +300,6 @@ void Document::removeScriptPragmas(QString &script) Document::Document(bool debugMode) : jsModule(debugMode) , program(0) - , indexOfRootObject(0) , jsGenerator(&jsModule) { } @@ -404,7 +403,10 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen QQmlJS::AST::UiObjectDefinition *rootObject = QQmlJS::AST::cast(program->members->member); Q_ASSERT(rootObject); - defineQMLObject(&output->indexOfRootObject, rootObject); + int rootObjectIndex = -1; + if (defineQMLObject(&rootObjectIndex, rootObject)) { + Q_ASSERT(rootObjectIndex == 0); + } qSwap(_imports, output->imports); qSwap(_pragmas, output->pragmas); @@ -1399,7 +1401,6 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4: qmlUnit->nImports = output.imports.count(); qmlUnit->offsetToObjects = unitSize + importSize; qmlUnit->nObjects = output.objects.count(); - qmlUnit->indexOfRootObject = output.indexOfRootObject; qmlUnit->offsetToStringTable = totalSize - output.jsGenerator.stringTable.sizeOfTableAndData(); qmlUnit->stringTableSize = output.jsGenerator.stringTable.stringCount(); @@ -2085,8 +2086,6 @@ void IRLoader::load() output->pragmas << p; } - output->indexOfRootObject = unit->indexOfRootObject; - for (uint i = 0; i < unit->nObjects; ++i) { const QV4::CompiledData::Object *serializedObject = unit->objectAt(i); QmlIR::Object *object = loadObject(serializedObject); diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 64bf111d9a..a6ff18927d 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -432,7 +432,6 @@ struct Q_QML_PRIVATE_EXPORT Document QList imports; QList pragmas; QQmlJS::AST::UiProgram *program; - int indexOfRootObject; QVector objects; QV4::Compiler::JSUnitGenerator jsGenerator; diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 2dd2e82651..22e83de9ae 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -108,7 +108,7 @@ template inline QQmlCompileError QQmlPropertyCacheCreator::buildMetaObjects() { QQmlBindingInstantiationContext context; - return buildMetaObjectRecursively(objectContainer->rootObjectIndex(), context); + return buildMetaObjectRecursively(/*root object*/0, context); } template @@ -278,7 +278,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator::createMetaObj QByteArray newClassName; - if (objectIndex == objectContainer->rootObjectIndex()) { + if (objectIndex == /*root object*/0) { const QString path = objectContainer->url().path(); int lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash > -1) { @@ -561,9 +561,9 @@ inline QQmlPropertyCacheAliasCreator::QQmlPropertyCacheAliasCre template inline void QQmlPropertyCacheAliasCreator::appendAliasPropertiesToMetaObjects() { - for (int i = 0; i < objectContainer->objectCount(); ++i) { - if (i == objectContainer->rootObjectIndex()) - continue; + // skip the root object (index 0) as that one does not have a first object index originating + // from a binding. + for (int i = 1; i < objectContainer->objectCount(); ++i) { const CompiledObject &component = *objectContainer->objectAt(i); if (!(component.flags & QV4::CompiledData::Object::IsComponent)) continue; @@ -572,7 +572,7 @@ inline void QQmlPropertyCacheAliasCreator::appendAliasPropertie appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex); } - const int rootObjectIndex = objectContainer->rootObjectIndex(); + const int rootObjectIndex = 0; appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex); } @@ -635,7 +635,7 @@ inline void QQmlPropertyCacheAliasCreator::collectObjectsWithAl objectsWithAliases->append(objectIndex); // Stop at Component boundary - if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != objectContainer->rootObjectIndex()) + if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != /*root object*/0) return; auto binding = object.bindingsBegin(); diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 6929318c59..7ea89b378d 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -58,7 +58,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c QVector QQmlPropertyValidator::validate() { - return validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0); + return validateObject(/*root object*/0, /*instantiatingBinding*/0); } typedef QVarLengthArray GroupPropertyVector; 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) diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 79fc073d8b..0e953ec01e 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -119,7 +119,6 @@ public: QQmlEnginePrivate *enginePrivate() const { return engine; } const QQmlImports *imports() const; QVector *qmlObjects() const; - int rootObjectIndex() const; void setPropertyCaches(QQmlPropertyCacheVector &&caches); const QQmlPropertyCacheVector *propertyCaches() const; QQmlPropertyCacheVector &&takePropertyCaches(); @@ -282,7 +281,6 @@ protected: QQmlJS::MemoryPool *pool; QVector *qmlObjects; - const int indexOfRootObject; // indices of the objects that are actually Component {} QVector componentRoots; diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 6702966d11..9e9a419be7 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -212,7 +212,7 @@ void CompilationUnit::unlink() engine->compilationUnits.erase(engine->compilationUnits.find(this)); if (isRegisteredWithEngine) { - Q_ASSERT(data && quint32(propertyCaches.count()) > data->indexOfRootObject && propertyCaches.at(data->indexOfRootObject)); + Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0)); if (qmlEngine) qmlEngine->unregisterInternalCompositeType(this); QQmlMetaType::unregisterInternalCompositeType(this); @@ -288,11 +288,11 @@ void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine) this->qmlEngine = qmlEngine; // Add to type registry of composites - if (propertyCaches.needsVMEMetaObject(data->indexOfRootObject)) { + if (propertyCaches.needsVMEMetaObject(/*root object*/0)) { QQmlMetaType::registerInternalCompositeType(this); qmlEngine->registerInternalCompositeType(this); } else { - const QV4::CompiledData::Object *obj = objectAt(data->indexOfRootObject); + const QV4::CompiledData::Object *obj = objectAt(/*root object*/0); auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); if (typeRef->compilationUnit) { diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 815c1b92de..6e6d641d94 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x12 +#define QV4_DATA_STRUCTURE_VERSION 0x13 class QIODevice; class QQmlPropertyCache; @@ -666,7 +666,6 @@ struct Unit LEUInt32 offsetToImports; LEUInt32 nObjects; LEUInt32 offsetToObjects; - LEUInt32 indexOfRootObject; LEUInt32 padding; @@ -854,7 +853,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public // QML specific fields QQmlPropertyCacheVector propertyCaches; - QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(data->indexOfRootObject); } + QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(/*root object*/0); } QQmlRefPointer typeNameCache; @@ -891,7 +890,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public // --- interface for QQmlPropertyCacheCreator typedef Object CompiledObject; int objectCount() const { return data->nObjects; } - int rootObjectIndex() const { return data->indexOfRootObject; } const Object *objectAt(int index) const { return data->objectAt(index); } QString stringAt(int index) const { return data->stringAt(index); } diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index ede432a1e0..3abdd0370f 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -432,7 +432,6 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp unit.offsetToImports = 0; unit.nObjects = 0; unit.offsetToObjects = 0; - unit.indexOfRootObject = 0; unit.unitSize = nextOffset; diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index e06491a814..37cb328b36 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -818,7 +818,7 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate() void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer &unit, int subComponentIndex) { typeCompilationUnit = unit; - componentObjectIndex = subComponentIndex == -1 ? typeCompilationUnit->data->indexOfRootObject : subComponentIndex; + componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex; Q_ASSERT(!idValues); idValueCount = typeCompilationUnit->data->objectAt(componentObjectIndex)->nNamedObjectsInComponent; idValues = new ContextGuard[idValueCount]; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 890d1ca7fe..07a90d4d63 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -163,7 +163,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI int objectToCreate; if (subComponentIndex == -1) { - objectToCreate = qmlUnit->indexOfRootObject; + objectToCreate = /*root object*/0; } else { const QV4::CompiledData::Object *compObj = qmlUnit->objectAt(subComponentIndex); objectToCreate = compObj->bindingTable()->value.objectIndex; @@ -1121,7 +1121,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } ddata->setImplicitDestructible(); - if (static_cast(index) == qmlUnit->indexOfRootObject || ddata->rootObjectInCreation) { + if (static_cast(index) == /*root object*/0 || ddata->rootObjectInCreation) { if (ddata->context) { Q_ASSERT(ddata->context != context); Q_ASSERT(ddata->outerContext); -- cgit v1.2.3 From 5f17840a14e22da0cfa973b36b9f6ce3bc8d4067 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 Sep 2017 10:34:45 +0200 Subject: Remove temporary allocations during type cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a follow-up commit to 48c09a85, avoid the use of key() to create a temporary string when cleaning the QML type registry. There is strictly speaking no need to perform another hash lookup anyway. Change-Id: Ibd5f0210d5584d1f847d8ec61f25cb0972076365 Reviewed-by: Pasi Petäjäjärvi Reviewed-by: Lars Knoll --- src/qml/qml/qqmlmetatype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index ca0522aa99..5bbc250d5e 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1215,7 +1215,7 @@ void QQmlTypeModulePrivate::add(QQmlTypePrivate *type) void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type) { for (TypeHash::ConstIterator elementIt = typeHash.begin(); elementIt != typeHash.end();) { - QList &list = typeHash[elementIt.key()]; + QList &list = const_cast &>(elementIt.value()); removeQQmlTypePrivate(list, type); -- cgit v1.2.3 From c1fed764a2495373a9e4563bc3ac0d578b2f9409 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 8 Aug 2017 12:39:54 +0200 Subject: Fix reuse of regexp objects by regexp literals Accoding to the standard the regexp objects created by literals should be separate objects as if calling new. We were violating that by caching the same object for every instance of a literal. This also fixes a problem with leaking values of lastIndex between separate instances of the same global regexp literal. Task-number: QTBUG-62175 Change-Id: Ib22e9ee68de1d1209fbd4212e72f576bc059d245 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4compileddata.cpp | 13 ++++++++----- src/qml/jsruntime/qv4engine.cpp | 16 ++++++---------- src/qml/jsruntime/qv4engine_p.h | 2 +- src/qml/jsruntime/qv4regexp.cpp | 9 +++++---- src/qml/jsruntime/qv4regexp_p.h | 13 +++++++++---- src/qml/jsruntime/qv4regexpobject.cpp | 14 +++++--------- src/qml/jsruntime/qv4regexpobject_p.h | 6 +++--- src/qml/jsruntime/qv4runtime.cpp | 7 ++++++- src/qml/jsruntime/qv4stringobject.cpp | 2 +- src/qml/jsruntime/qv4vme_moth.cpp | 7 ++++++- 10 files changed, 50 insertions(+), 39 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 9e9a419be7..34491a3a84 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -136,14 +137,16 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value)); for (uint i = 0; i < data->regexpTableSize; ++i) { const CompiledData::RegExp *re = data->regexpAt(i); - int flags = 0; + bool global = false; + bool multiline = false; + bool ignoreCase = false; if (re->flags & CompiledData::RegExp::RegExp_Global) - flags |= IR::RegExp::RegExp_Global; + global = true; if (re->flags & CompiledData::RegExp::RegExp_IgnoreCase) - flags |= IR::RegExp::RegExp_IgnoreCase; + ignoreCase = true; if (re->flags & CompiledData::RegExp::RegExp_Multiline) - flags |= IR::RegExp::RegExp_Multiline; - runtimeRegularExpressions[i] = engine->newRegExpObject(data->stringAt(re->stringIndex), flags); + multiline = true; + runtimeRegularExpressions[i] = QV4::RegExp::create(engine, data->stringAt(re->stringIndex), ignoreCase, multiline, global); } if (data->lookupTableSize) { diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 5e776ea09b..a090ac7c47 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -660,21 +660,17 @@ Heap::DateObject *ExecutionEngine::newDateObjectFromTime(const QTime &t) Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags) { bool global = (flags & IR::RegExp::RegExp_Global); - bool ignoreCase = false; - bool multiline = false; - if (flags & IR::RegExp::RegExp_IgnoreCase) - ignoreCase = true; - if (flags & IR::RegExp::RegExp_Multiline) - multiline = true; + bool ignoreCase = (flags & IR::RegExp::RegExp_IgnoreCase); + bool multiline = (flags & IR::RegExp::RegExp_Multiline); Scope scope(this); - Scoped re(scope, RegExp::create(this, pattern, ignoreCase, multiline)); - return newRegExpObject(re, global); + Scoped re(scope, RegExp::create(this, pattern, ignoreCase, multiline, global)); + return newRegExpObject(re); } -Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re, bool global) +Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re) { - return memoryManager->allocObject(re, global); + return memoryManager->allocObject(re); } Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index d331fd7bff..688a58e345 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -391,7 +391,7 @@ public: Heap::DateObject *newDateObjectFromTime(const QTime &t); Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags); - Heap::RegExpObject *newRegExpObject(RegExp *re, bool global); + Heap::RegExpObject *newRegExpObject(RegExp *re); Heap::RegExpObject *newRegExpObject(const QRegExp &re); Heap::Object *newErrorObject(const Value &value); diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 9e94c58432..8cb15b9d7e 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -69,9 +69,9 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) return JSC::Yarr::interpret(byteCode(), s.characters16(), string.length(), start, matchOffsets); } -Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline) +Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline, bool global) { - RegExpCacheKey key(pattern, ignoreCase, multiline); + RegExpCacheKey key(pattern, ignoreCase, multiline, global); RegExpCache *cache = engine->regExpCache; if (!cache) @@ -82,7 +82,7 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo return result->d(); Scope scope(engine); - Scoped result(scope, engine->memoryManager->alloc(engine, pattern, ignoreCase, multiline)); + Scoped result(scope, engine->memoryManager->alloc(engine, pattern, ignoreCase, multiline, global)); result->d()->cache = cache; cachedValue.set(engine, result); @@ -90,12 +90,13 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo return result->d(); } -void Heap::RegExp::init(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) +void Heap::RegExp::init(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline, bool global) { Base::init(); this->pattern = new QString(pattern); this->ignoreCase = ignoreCase; this->multiLine = multiline; + this->global = global; const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 04cdb468bf..d9b536406c 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -76,7 +76,7 @@ struct RegExpCacheKey; namespace Heap { struct RegExp : Base { - void init(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); + void init(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline, bool global); void destroy(); QString *pattern; @@ -88,6 +88,7 @@ struct RegExp : Base { int subPatternCount; bool ignoreCase; bool multiLine; + bool global; int captureCount() const { return subPatternCount + 1; } }; @@ -111,8 +112,9 @@ struct RegExp : public Managed int subPatternCount() const { return d()->subPatternCount; } bool ignoreCase() const { return d()->ignoreCase; } bool multiLine() const { return d()->multiLine; } + bool global() const { return d()->global; } - static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); + static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false, bool global = false); bool isValid() const { return d()->byteCode; } @@ -127,27 +129,30 @@ struct RegExp : public Managed struct RegExpCacheKey { - RegExpCacheKey(const QString &pattern, bool ignoreCase, bool multiLine) + RegExpCacheKey(const QString &pattern, bool ignoreCase, bool multiLine, bool global) : pattern(pattern) , ignoreCase(ignoreCase) , multiLine(multiLine) + , global(global) { } explicit inline RegExpCacheKey(const RegExp::Data *re); bool operator==(const RegExpCacheKey &other) const - { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine; } + { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine && global == other.global; } bool operator!=(const RegExpCacheKey &other) const { return !operator==(other); } QString pattern; uint ignoreCase : 1; uint multiLine : 1; + uint global : 1; }; inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re) : pattern(*re->pattern) , ignoreCase(re->ignoreCase) , multiLine(re->multiLine) + , global(re->global) {} inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 1f758e36f6..82b0f67075 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -74,15 +74,13 @@ void Heap::RegExpObject::init() Object::init(); Scope scope(internalClass->engine); Scoped o(scope, this); - o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false); - o->d()->global = false; + o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false, false); o->initProperties(); } -void Heap::RegExpObject::init(QV4::RegExp *value, bool global) +void Heap::RegExpObject::init(QV4::RegExp *value) { Object::init(); - this->global = global; this->value = value->d(); Scope scope(internalClass->engine); Scoped o(scope, this); @@ -95,7 +93,6 @@ void Heap::RegExpObject::init(QV4::RegExp *value, bool global) void Heap::RegExpObject::init(const QRegExp &re) { Object::init(); - global = false; // Convert the pattern to a ECMAScript pattern. QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax()); @@ -246,7 +243,7 @@ void RegExpCtor::construct(const Managed *, Scope &scope, CallData *callData) } Scoped regexp(scope, re->value()); - scope.result = Encode(scope.engine->newRegExpObject(regexp, re->global())); + scope.result = Encode(scope.engine->newRegExpObject(regexp)); return; } @@ -282,13 +279,13 @@ void RegExpCtor::construct(const Managed *, Scope &scope, CallData *callData) } } - Scoped regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine)); + Scoped regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine, global)); if (!regexp->isValid()) { scope.result = scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression")); return; } - scope.result = Encode(scope.engine->newRegExpObject(regexp, global)); + scope.result = Encode(scope.engine->newRegExpObject(regexp)); } void RegExpCtor::call(const Managed *that, Scope &scope, CallData *callData) @@ -433,7 +430,6 @@ void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, Call Scoped re(scope, scope.result.asReturnedValue()); r->d()->value = re->value(); - r->d()->global = re->global(); RETURN_UNDEFINED(); } diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 54731cef14..af49a1bf5e 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -60,6 +60,7 @@ #include "qv4managed_p.h" #include "qv4property_p.h" #include "qv4objectiterator_p.h" +#include "qv4regexp_p.h" #include #include @@ -75,11 +76,10 @@ namespace Heap { struct RegExpObject : Object { void init(); - void init(QV4::RegExp *value, bool global); + void init(QV4::RegExp *value); void init(const QRegExp &re); Pointer value; - bool global; }; struct RegExpCtor : FunctionObject { @@ -117,7 +117,7 @@ struct RegExpObject: Object { }; Heap::RegExp *value() const { return d()->value; } - bool global() const { return d()->global; } + bool global() const { return d()->value->global; } void initProperties(); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index ecf2fd8b11..28b344d154 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -51,6 +51,8 @@ #include "qv4lookup_p.h" #include "qv4function_p.h" #include "qv4numberobject_p.h" +#include "qv4regexp_p.h" +#include "qv4regexpobject_p.h" #include "private/qlocale_tools_p.h" #include "qv4scopedvalue_p.h" #include @@ -1477,7 +1479,10 @@ ReturnedValue Runtime::method_getQmlContext(NoThrowEngine *engine) ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id) { - return static_cast(engine->current->compilationUnit)->runtimeRegularExpressions[id].asReturnedValue(); + Heap::RegExpObject *ro = engine->newRegExpObject( + static_cast(engine->current->compilationUnit) + ->runtimeRegularExpressions[id].as()); + return ro->asReturnedValue(); } ReturnedValue Runtime::method_getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 1596f4b0fa..7ccb7a762f 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -542,7 +542,7 @@ void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, Call break; } nMatchOffsets += re->captureCount() * 2; - if (!regExp->d()->global) + if (!regExp->global()) break; offset = qMax(offset + 1, matchOffsets[oldSize + 1]); } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 9d65f67f0f..3d95353fc0 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -443,7 +445,10 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code) MOTH_BEGIN_INSTR(LoadRegExp) // TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData()); - VALUE(instr.result) = static_cast(engine->current->compilationUnit)->runtimeRegularExpressions[instr.regExpId]; + Heap::RegExpObject *ro = engine->newRegExpObject( + static_cast(engine->current->compilationUnit) + ->runtimeRegularExpressions[instr.regExpId].as()); + VALUE(instr.result) = ro; MOTH_END_INSTR(LoadRegExp) MOTH_BEGIN_INSTR(LoadClosure) -- cgit v1.2.3 From 38ef59b386e5eb5063b9572d2dfc1a7d59624ef3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 8 Sep 2017 15:20:02 +0200 Subject: Drain the mark stack while collecting roots This avoids overflows in the markStack for test cases where we have a huge amount of compilation units with many runtime strings that all want to get marked. Task-number: QTBUG-63063 Change-Id: I150c1f1a4065350cec59dd80c5c628920f70e3d0 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index a090ac7c47..d571337ecf 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -927,8 +927,18 @@ void ExecutionEngine::requireArgumentsAccessors(int n) } } +static void drainMarkStack(ExecutionEngine *engine, Value *markBase) +{ + while (engine->jsStackTop > markBase) { + Heap::Base *h = engine->popForGC(); + Q_ASSERT (h->vtable()->markObjects); + h->vtable()->markObjects(h, engine); + } +} + void ExecutionEngine::markObjects() { + Value *markBase = jsStackTop; identifierTable->mark(this); for (int i = 0; i < nArgumentsAccessors; ++i) { @@ -941,9 +951,13 @@ void ExecutionEngine::markObjects() classPool->markObjects(this); + drainMarkStack(this, markBase); + for (QSet::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd(); - it != end; ++it) + it != end; ++it) { (*it)->markObjects(this); + drainMarkStack(this, markBase); + } } ReturnedValue ExecutionEngine::throwError(const Value &value) -- cgit v1.2.3 From 9fd39f34f7512d199a1f68dcff4f50e469897e31 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 11 Sep 2017 13:49:51 +0200 Subject: Update the expected size of QV4::CompiledData::Unit ebda8170a removed a member. Thanks to the padding, the size of the structure remained the same on 64-bit, but not on 32-bit. Removing the padding gives now the same size on both. Task-number: QTBUG-63109 Change-Id: If87ad21a1c94e63643b0cd52f95e244364f6e73d Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata_p.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 6e6d641d94..84777b3533 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -667,8 +667,6 @@ struct Unit LEUInt32 nObjects; LEUInt32 offsetToObjects; - LEUInt32 padding; - const Import *importAt(int idx) const { return reinterpret_cast((reinterpret_cast(this)) + offsetToImports + idx * sizeof(Import)); } @@ -733,7 +731,7 @@ struct Unit } }; -static_assert(sizeof(Unit) == 152, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Unit) == 144, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct TypeReference { -- cgit v1.2.3 From a763d6a88be732de4beb3c28dbe2cde7a063c83a Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 7 Sep 2017 22:20:14 -0700 Subject: Add missing math.h include for math functions On some platforms, math functions in the std namespace don't work even if cmath is included. Change-Id: Ia71d22b07f508e0584de5320f376fbf4b3a2887b Reviewed-by: Thiago Macieira --- src/qml/jsruntime/qv4mathobject.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 2d9d81c64b..109d6c38b5 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -45,6 +45,7 @@ #include #include +#include #include using namespace QV4; -- cgit v1.2.3 From 78d574a909a4bcf7543fba8d921e8658dfbc0200 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Sep 2017 10:14:52 +0200 Subject: Fix Integrity build Disambiguate the QV4::Value parameter. Task-number: QTBUG-63135 Change-Id: Iae6bd209876336d58256aa94f89d146cadc62f08 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index d571337ecf..54011e6bd2 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -927,7 +927,7 @@ void ExecutionEngine::requireArgumentsAccessors(int n) } } -static void drainMarkStack(ExecutionEngine *engine, Value *markBase) +static void drainMarkStack(ExecutionEngine *engine, QV4::Value *markBase) { while (engine->jsStackTop > markBase) { Heap::Base *h = engine->popForGC(); -- cgit v1.2.3 From 98358715930739ca8de172d88c5ce6941c275ff3 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Sep 2017 15:13:33 +0200 Subject: Fix qml cache invalidation when changing dependent C++ registered QML singletons When a qml file uses a qml singleton, we need to reliably detect when the singleton changes and re-generate the cache of the qml file using it. This is a scenario covered and fixed by commit 5b94de09cc738837d1539e28b3c0dccd17c18d29, with the exception that currently QML singletons registered via qmlRegisterSingleton were not added to the list of dependent singletons for a qml file. We can fix this by extending findCompositeSingletons() to also cover the singletons that do not originate from a qmldir file. [ChangeLog][Qt][Qml] Fixed bug where sometimes changes to a qml singleton would not propagate to the users or cause crashes. Task-number: QTBUG-62243 Change-Id: I16c3d9ba65fd82e898a29b946c341907751135a9 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlimport.cpp | 11 +++++++++++ src/qml/qml/qqmlmetatype.cpp | 12 ++++++++++++ src/qml/qml/qqmlmetatype_p.h | 2 ++ 3 files changed, 25 insertions(+) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 0bd7317470..ccd287e1b6 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -471,6 +471,17 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QListuri, import->majversion)) { + module->walkCompositeSingletons([&resultList, &set](const QQmlType &singleton) { + QQmlImports::CompositeSingletonReference ref; + ref.typeName = singleton.elementName(); + ref.prefix = set.prefix; + ref.majorVersion = singleton.majorVersion(); + ref.minorVersion = singleton.minorVersion(); + resultList.append(ref); + }); + } } } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 5bbc250d5e..8f5d11a96f 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1258,6 +1258,18 @@ QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const return QQmlType(); } +void QQmlTypeModule::walkCompositeSingletons(const std::function &callback) const +{ + QMutexLocker lock(metaTypeDataLock()); + for (auto typeCandidates = d->typeHash.begin(), end = d->typeHash.end(); + typeCandidates != end; ++typeCandidates) { + for (auto type: typeCandidates.value()) { + if (type->regType == QQmlType::CompositeSingletonType) + callback(QQmlType(type)); + } + } +} + QQmlTypeModuleVersion::QQmlTypeModuleVersion() : m_module(0), m_minor(0) { diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index ac2133ba30..9a7736ffcd 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -298,6 +298,8 @@ public: QQmlType type(const QHashedStringRef &, int) const; QQmlType type(const QV4::String *, int) const; + void walkCompositeSingletons(const std::function &callback) const; + QQmlTypeModulePrivate *priv() { return d; } private: //Used by register functions and creates the QQmlTypeModule for them -- cgit v1.2.3 From 215c0145be7119a0e885ff95a17ee7aebd17ad12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 6 Sep 2017 12:43:16 +0200 Subject: qmltest: Enumerate test cases / functions without evaluating QML Most, if not all, QML tests are written without any sort of dynamic instantiation of the test data, so doing view.setSource() will evaluate the whole source file, compute bindings, create items, windows, etc. This is less then ideal when all you want is to list the test functions using -functions, or when running a single test from the command line, as in both cases we'll still actually evaluate every single QML file. This makes it really hard to evaluate test output, e.g. from the CI, especially with logging enabled, as even if a single test is requested, the logs are filled with results from the loading of the other tests. To improve the situation we use a non-instantiated QML component that we then inspect its compilation data, looking for test cases and functions. In the future the implementation of TestCase's qtest_run* machinery should be built on top of QTestLib instead of being reimplemented in JavaScript, but this is left for later. Change-Id: Ie5448208daf786e335583ab6bdfbc195891ec1f5 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypenamecache_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h index 6e5cd0fb54..8ac25c4fbe 100644 --- a/src/qml/qml/qqmltypenamecache_p.h +++ b/src/qml/qml/qqmltypenamecache_p.h @@ -81,7 +81,7 @@ struct QQmlImportRef { class QQmlType; class QQmlEngine; -class QQmlTypeNameCache : public QQmlRefCount +class Q_QML_PRIVATE_EXPORT QQmlTypeNameCache : public QQmlRefCount { public: QQmlTypeNameCache(const QQmlImports &imports); -- cgit v1.2.3 From e29ffa179e9920443a23e2fcb3f0694df32e8a68 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 14 Sep 2017 13:47:14 +0200 Subject: Fix use-after-free when removing elements from a ListModel Detaching delegate instances from model items is done after the destruction of said model items. The problem is that after the model item is destroyed, it will emit a change/destroyed signal. As the delegate is still referencing the item, this will result in a use-after-free. To provent that, the items are kept around until after everyone (notably the delegate model) has been notified of the removal. [ChangeLog][Qt][Qml] Fix possible use-after-free when removing items from a ListModel through JavaScript. Task-number: QTBUG-59256 Change-Id: Iee182e2cf0b50d3dda2181fed95e38f1a60f22a9 Reviewed-by: Simon Hausmann --- src/qml/types/qqmldelegatemodel.cpp | 7 +++++++ src/qml/types/qqmllistmodel.cpp | 25 +++++++++++++++++++------ src/qml/types/qqmllistmodel_p_p.h | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'src/qml') diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 9b1417eccd..26e6a81418 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1266,6 +1266,13 @@ void QQmlDelegateModel::_q_itemsInserted(int index, int count) d->emitChanges(); } +//### This method should be split in two. It will remove delegates, and it will re-render the list. +// When e.g. QQmlListModel::remove is called, the removal of the delegates should be done on +// QAbstractItemModel::rowsAboutToBeRemoved, and the re-rendering on +// QAbstractItemModel::rowsRemoved. Currently both are done on the latter signal. The problem is +// that the destruction of an item will emit a changed signal that ends up at the delegate, which +// in turn will try to load the data from the model (which should have already freed it), resulting +// in a use-after-free. See QTBUG-59256. void QQmlDelegateModelPrivate::itemsRemoved( const QVector &removes, QVarLengthArray, Compositor::MaximumGroupCount> *translatedRemoves, diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 9d0f1afb32..b33be2b4fb 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -567,14 +567,20 @@ void ListModel::clear() elements.clear(); } -void ListModel::remove(int index, int count) +QVector> ListModel::remove(int index, int count) { + QVector> toDestroy; + auto layout = m_layout; for (int i=0 ; i < count ; ++i) { - elements[index+i]->destroy(m_layout); - delete elements[index+i]; + auto element = elements[index+i]; + toDestroy.append([element, layout](){ + element->destroy(layout); + delete element; + }); } elements.remove(index, count); updateCacheIndices(); + return toDestroy; } void ListModel::insert(int elementIndex, QV4::Object *object) @@ -2053,15 +2059,22 @@ void QQmlListModel::remove(QQmlV4Function *args) emitItemsAboutToBeRemoved(index, removeCount); + QVector> toDestroy; if (m_dynamicRoles) { - for (int i=0 ; i < removeCount ; ++i) - delete m_modelObjects[index+i]; + for (int i=0 ; i < removeCount ; ++i) { + auto modelObject = m_modelObjects[index+i]; + toDestroy.append([modelObject](){ + delete modelObject; + }); + } m_modelObjects.remove(index, removeCount); } else { - m_listModel->remove(index, removeCount); + toDestroy = m_listModel->remove(index, removeCount); } emitItemsRemoved(index, removeCount); + for (const auto &destroyer : toDestroy) + destroyer(); } else { qmlWarning(this) << tr("remove: incorrect number of arguments"); } diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index cdce78e542..4928ad3725 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -367,7 +367,7 @@ public: void insert(int elementIndex, QV4::Object *object); void clear(); - void remove(int index, int count); + Q_REQUIRED_RESULT QVector> remove(int index, int count); int appendElement(); void insertElement(int index); -- cgit v1.2.3 From a361e62a9fedabc7bd4c57d933bf78468fdc6795 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 3 Dec 2015 23:36:48 -0800 Subject: Use the qEnvironmentVariable function from QtCore This corrects the encoding of QML2_IMPORT_PATH environment variable, since it contains paths. For the other cases, it's just improving the code. Task-number: QTBUG-62328 Change-Id: I0f2ce894387048f78465ffff141ca50208f6845a Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 7c9dcb1826..66c0be41da 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1699,13 +1699,13 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) // env import paths if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) { - const QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH"); + const QString envImportPath = qEnvironmentVariable("QML2_IMPORT_PATH"); #if defined(Q_OS_WIN) QLatin1Char pathSep(';'); #else QLatin1Char pathSep(':'); #endif - QStringList paths = QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts); + QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts); for (int ii = paths.count() - 1; ii >= 0; --ii) addImportPath(paths.at(ii)); } -- cgit v1.2.3 From bfab1db38167d31f0487f96d2d4b02d9243bc777 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 15 Sep 2017 13:56:36 +0200 Subject: Fall back to the ObjectWrapper for model advanceIterator When falling back to the QObjectWrapper it will add in the extra parts added when the roles were added to the object created by the model to hold the data being returned. This was causing the last entry to be duplicated and causing extra work too. Task-number: QTBUG-54285 Task-number: QTBUG-62156 Change-Id: I2907477277df8d16db4491a4999f004433e4205c Reviewed-by: Simon Hausmann --- src/qml/types/qqmllistmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index b33be2b4fb..35ee30dccf 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -1394,7 +1394,10 @@ void ModelObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, u p->value = v4->fromVariant(value); return; } - QV4::QObjectWrapper::advanceIterator(m, it, name, index, p, attributes); + // Fall back to QV4::Object as opposed to QV4::QObjectWrapper otherwise it will add + // unnecessary entries that relate to the roles used. These just create extra work + // later on as they will just be ignored. + QV4::Object::advanceIterator(m, it, name, index, p, attributes); } DEFINE_OBJECT_VTABLE(ModelObject); -- cgit v1.2.3 From 71a18fd64c93afa00f4d89de2ba47663f41eba2c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 18 Sep 2017 16:26:17 +0200 Subject: Fix qmlClearTypeRegistrations() not dropping all registrations In commit 48c09a85ce397979c7e706e3694c879ffe456e09 we added the undeletableTypes container to hold a reference on C++ registered types to keep the indices returned by the public qmlRegisterType() API stable. Since qmlClearTypeRegistrations() is API that also resets those indices, we must also clear the undeletableTypes container to avoid leaking memory. Change-Id: I2038c00913f894d58aca3714d64d497493585326 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlmetatype.cpp | 8 ++++++++ src/qml/qml/qqmlmetatype_p.h | 1 + 2 files changed, 9 insertions(+) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 8f5d11a96f..ac670bdabb 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1144,6 +1144,13 @@ void QQmlType::derefHandle(QQmlTypePrivate *priv) delete priv; } +int QQmlType::refCount(QQmlTypePrivate *priv) +{ + if (priv) + return priv->refCount; + return -1; +} + namespace { template void removeQQmlTypePrivate(QQmlTypeContainer &container, const QQmlTypePrivate *reference) @@ -1334,6 +1341,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h data->urlToNonFileImportType.clear(); data->metaObjectToType.clear(); data->uriToModule.clear(); + data->undeletableTypes.clear(); QQmlEnginePrivate::baseModulesUninitialized = true; //So the engine re-registers its types #if QT_CONFIG(library) diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 9a7736ffcd..74b1cf0e06 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -245,6 +245,7 @@ public: QQmlTypePrivate *priv() const { return d; } static void refHandle(QQmlTypePrivate *priv); static void derefHandle(QQmlTypePrivate *priv); + static int refCount(QQmlTypePrivate *priv); enum RegistrationType { CppType = 0, -- cgit v1.2.3 From 82fbaa78f3840bcc289adc4e1ec64e337346f148 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 29 Nov 2013 14:04:27 +0100 Subject: Fix support for creating QWidgets in QML When creating QWidgets, it is important to replace any call to QObject::setParent with QWidget::setParent. We do this now with the hook introduced in commit fc8adfea9f5e09e5f47ac4e592e5d9db471caede in qtbase. Change-Id: I2e069696b7ceb7f3b77d0f17e058f5a00ca4a029 Reviewed-by: Edward Welbourne Reviewed-by: Lars Knoll --- src/qml/qml/qqmlobjectcreator.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 11d090a415..26bdf1a94f 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1113,8 +1113,16 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo return 0; } } - if (parent) + if (instance->isWidgetType()) { + if (parent && parent->isWidgetType()) { + QAbstractDeclarativeData::setWidgetParent(instance, parent); + } else { + // No parent! Layouts need to handle this through a default property that + // reparents accordingly. Otherwise the garbage collector will collect. + } + } else if (parent) { QQml_setParent_noEvent(instance, parent); + } ddata = QQmlData::get(instance, /*create*/true); ddata->lineNumber = obj->location.line; -- cgit v1.2.3 From 681f93c74d7d60dc1998d3124e1f59ddc0f476ee Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Wed, 20 Sep 2017 20:57:39 +0200 Subject: Replace Q_DECL_OVERRIDE with override Change-Id: I176f91a8c51e81a2df3fe91733118261491223ee Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata_p.h | 2 +- src/qml/compiler/qv4isel_moth_p.h | 14 +++++++------- src/qml/compiler/qv4ssa.cpp | 4 ++-- src/qml/jit/qv4assembler_p.h | 8 ++++---- src/qml/jit/qv4isel_masm_p.h | 6 +++--- src/qml/jit/qv4regalloc.cpp | 4 ++-- src/qml/qml/qqmlbinding.cpp | 10 +++++----- src/qml/qml/qqmlbinding_p.h | 6 +++--- src/qml/qml/qqmlvmemetaobject_p.h | 6 +++--- src/qml/types/qqmllistmodel_p.h | 4 ++-- 10 files changed, 32 insertions(+), 32 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index ce54e4fae4..a06b53e6e8 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -955,7 +955,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public void markObjects(MarkStack *markStack); - void destroy() Q_DECL_OVERRIDE; + void destroy() override; bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, EvalISelFactory *iselFactory, QString *errorString); diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 4b84bd2831..27e4e45449 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -72,11 +72,11 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit { virtual ~CompilationUnit(); #if !defined(V4_BOOTSTRAP) - void linkBackendToEngine(QV4::ExecutionEngine *engine) Q_DECL_OVERRIDE; - bool memoryMapCode(QString *errorString) Q_DECL_OVERRIDE; + void linkBackendToEngine(QV4::ExecutionEngine *engine) override; + bool memoryMapCode(QString *errorString) override; #endif - void prepareCodeOffsetsForDiskStorage(CompiledData::Unit *unit) Q_DECL_OVERRIDE; - bool saveCodeToDisk(QIODevice *device, const CompiledData::Unit *unit, QString *errorString) Q_DECL_OVERRIDE; + void prepareCodeOffsetsForDiskStorage(CompiledData::Unit *unit) override; + bool saveCodeToDisk(QIODevice *device, const CompiledData::Unit *unit, QString *errorString) override; QVector codeRefs; @@ -216,11 +216,11 @@ class Q_QML_EXPORT ISelFactory: public EvalISelFactory public: ISelFactory() : EvalISelFactory(QStringLiteral("moth")) {} virtual ~ISelFactory() {} - EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) Q_DECL_OVERRIDE Q_DECL_FINAL + EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) override Q_DECL_FINAL { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); } - bool jitCompileRegexps() const Q_DECL_OVERRIDE Q_DECL_FINAL + bool jitCompileRegexps() const override Q_DECL_FINAL { return false; } - QQmlRefPointer createUnitForLoading() Q_DECL_OVERRIDE; + QQmlRefPointer createUnitForLoading() override; }; diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 8cf5fac760..ab859c407e 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -2068,7 +2068,7 @@ public: } protected: - void visitTemp(Temp *e) Q_DECL_OVERRIDE Q_DECL_FINAL + void visitTemp(Temp *e) override Q_DECL_FINAL { _collectedTemps.append(e); } @@ -5108,7 +5108,7 @@ private: return checker.seenSideEffects(); } - void visitTemp(Temp *) Q_DECL_OVERRIDE Q_DECL_FINAL {} + void visitTemp(Temp *) override Q_DECL_FINAL {} }; void mergeBasicBlocks(IR::Function *function, DefUses *du, DominatorTree *dt) diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 9e38696d7a..2ae4818814 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -80,11 +80,11 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit virtual ~CompilationUnit(); #if !defined(V4_BOOTSTRAP) - void linkBackendToEngine(QV4::ExecutionEngine *engine) Q_DECL_OVERRIDE; - bool memoryMapCode(QString *errorString) Q_DECL_OVERRIDE; + void linkBackendToEngine(QV4::ExecutionEngine *engine) override; + bool memoryMapCode(QString *errorString) override; #endif - void prepareCodeOffsetsForDiskStorage(CompiledData::Unit *unit) Q_DECL_OVERRIDE; - bool saveCodeToDisk(QIODevice *device, const CompiledData::Unit *unit, QString *errorString) Q_DECL_OVERRIDE; + void prepareCodeOffsetsForDiskStorage(CompiledData::Unit *unit) override; + bool saveCodeToDisk(QIODevice *device, const CompiledData::Unit *unit, QString *errorString) override; // Coderef + execution engine diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 7019a117a2..8af029f5db 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -302,11 +302,11 @@ class Q_QML_EXPORT ISelFactory: public EvalISelFactory public: ISelFactory() : EvalISelFactory(QStringLiteral("jit")) {} virtual ~ISelFactory() {} - EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) Q_DECL_OVERRIDE Q_DECL_FINAL + EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) override Q_DECL_FINAL { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); } - bool jitCompileRegexps() const Q_DECL_OVERRIDE Q_DECL_FINAL + bool jitCompileRegexps() const override Q_DECL_FINAL { return true; } - QQmlRefPointer createUnitForLoading() Q_DECL_OVERRIDE Q_DECL_FINAL; + QQmlRefPointer createUnitForLoading() override Q_DECL_FINAL; }; } // end of namespace JIT diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index d418b050c4..5363f1f18b 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -87,7 +87,7 @@ public: {} protected: - void addStmtNr(Stmt *s) Q_DECL_OVERRIDE Q_DECL_FINAL + void addStmtNr(Stmt *s) override Q_DECL_FINAL { addJustifiedNr(intervals->positionForStatement(s)); } @@ -115,7 +115,7 @@ public: } protected: - void visitTemp(Temp *e) Q_DECL_OVERRIDE Q_DECL_FINAL + void visitTemp(Temp *e) override Q_DECL_FINAL { switch (e->kind) { case Temp::PhysicalRegister: { diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 566fbb86ac..0a241a92e8 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -180,7 +180,7 @@ class QQmlBindingBinding: public QQmlBinding { protected: void doUpdate(const DeleteWatcher &, - QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags, QV4::Scope &) override Q_DECL_FINAL { Q_ASSERT(!m_targetIndex.hasValueTypeIndex()); QQmlPropertyData *pd = nullptr; @@ -196,7 +196,7 @@ class QQmlNonbindingBinding: public QQmlBinding { protected: void doUpdate(const DeleteWatcher &watcher, - QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE + QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) override { auto ep = QQmlEnginePrivate::get(scope.engine); ep->referenceScarceResources(); @@ -238,7 +238,7 @@ class GenericBinding: public QQmlNonbindingBinding protected: // Returns true if successful, false if an error description was set on expression Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined, - QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags) override Q_DECL_FINAL { Q_ASSERT(targetObject()); @@ -307,7 +307,7 @@ public: } void doUpdate(const DeleteWatcher &watcher, - QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags, QV4::Scope &) override Q_DECL_FINAL { if (watcher.wasDeleted()) return; @@ -622,7 +622,7 @@ public: protected: Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined, - QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags) override Q_DECL_FINAL { QQmlPropertyData *pd; QQmlPropertyData vtpd; diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 38d59a8919..8bc9554a42 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -86,10 +86,10 @@ public: void setNotifyOnValueChanged(bool); - void refresh() Q_DECL_OVERRIDE; + void refresh() override; - void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) Q_DECL_OVERRIDE; - QString expression() const Q_DECL_OVERRIDE; + void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) override; + QString expression() const override; void update(QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding); typedef int Identifier; diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index ea5e9c0904..be1936cfb0 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -101,7 +101,7 @@ public: static QQmlInterceptorMetaObject *get(QObject *obj); - QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) Q_DECL_OVERRIDE; + QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) override; // Used by auto-tests for inspection QQmlPropertyCache *propertyCache() const { return cache; } @@ -116,7 +116,7 @@ public: } protected: - int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) Q_DECL_OVERRIDE; + int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) override; bool intercept(QMetaObject::Call c, int id, void **a); public: @@ -161,7 +161,7 @@ public: static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex); protected: - int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) Q_DECL_OVERRIDE; + int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; public: QV4::ExecutionEngine *engine; diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h index b750d30676..372b7c70c7 100644 --- a/src/qml/types/qqmllistmodel_p.h +++ b/src/qml/types/qqmllistmodel_p.h @@ -187,8 +187,8 @@ public: QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {} - void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList &bindings) Q_DECL_OVERRIDE; - void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList &bindings) Q_DECL_OVERRIDE; + void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList &bindings) override; + void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList &bindings) override; private: bool verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding); -- cgit v1.2.3 From 11d34cc67d6db1c0acb9db2f4b105d0cd538fb65 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Thu, 21 Sep 2017 17:14:49 +0200 Subject: Replace Q_DECL_FINAL with final Change-Id: I4268b15226b9b597a4a2486a094701db17aa1440 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4isel_moth_p.h | 4 ++-- src/qml/compiler/qv4ssa.cpp | 4 ++-- src/qml/jit/qv4isel_masm_p.h | 6 +++--- src/qml/jit/qv4regalloc.cpp | 4 ++-- src/qml/qml/qqmlbinding.cpp | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 27e4e45449..db49177783 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -216,9 +216,9 @@ class Q_QML_EXPORT ISelFactory: public EvalISelFactory public: ISelFactory() : EvalISelFactory(QStringLiteral("moth")) {} virtual ~ISelFactory() {} - EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) override Q_DECL_FINAL + EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) override final { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); } - bool jitCompileRegexps() const override Q_DECL_FINAL + bool jitCompileRegexps() const override final { return false; } QQmlRefPointer createUnitForLoading() override; diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index ab859c407e..cf79168c6c 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -2068,7 +2068,7 @@ public: } protected: - void visitTemp(Temp *e) override Q_DECL_FINAL + void visitTemp(Temp *e) override final { _collectedTemps.append(e); } @@ -5108,7 +5108,7 @@ private: return checker.seenSideEffects(); } - void visitTemp(Temp *) override Q_DECL_FINAL {} + void visitTemp(Temp *) override final {} }; void mergeBasicBlocks(IR::Function *function, DefUses *du, DominatorTree *dt) diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 8af029f5db..869f857c41 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -302,11 +302,11 @@ class Q_QML_EXPORT ISelFactory: public EvalISelFactory public: ISelFactory() : EvalISelFactory(QStringLiteral("jit")) {} virtual ~ISelFactory() {} - EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) override Q_DECL_FINAL + EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) override final { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); } - bool jitCompileRegexps() const override Q_DECL_FINAL + bool jitCompileRegexps() const override final { return true; } - QQmlRefPointer createUnitForLoading() override Q_DECL_FINAL; + QQmlRefPointer createUnitForLoading() override final; }; } // end of namespace JIT diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 5363f1f18b..cd2d53ab40 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -87,7 +87,7 @@ public: {} protected: - void addStmtNr(Stmt *s) override Q_DECL_FINAL + void addStmtNr(Stmt *s) override final { addJustifiedNr(intervals->positionForStatement(s)); } @@ -115,7 +115,7 @@ public: } protected: - void visitTemp(Temp *e) override Q_DECL_FINAL + void visitTemp(Temp *e) override final { switch (e->kind) { case Temp::PhysicalRegister: { diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 0a241a92e8..43ab74138c 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -180,7 +180,7 @@ class QQmlBindingBinding: public QQmlBinding { protected: void doUpdate(const DeleteWatcher &, - QQmlPropertyData::WriteFlags flags, QV4::Scope &) override Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags, QV4::Scope &) override final { Q_ASSERT(!m_targetIndex.hasValueTypeIndex()); QQmlPropertyData *pd = nullptr; @@ -238,7 +238,7 @@ class GenericBinding: public QQmlNonbindingBinding protected: // Returns true if successful, false if an error description was set on expression Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined, - QQmlPropertyData::WriteFlags flags) override Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags) override final { Q_ASSERT(targetObject()); @@ -307,7 +307,7 @@ public: } void doUpdate(const DeleteWatcher &watcher, - QQmlPropertyData::WriteFlags flags, QV4::Scope &) override Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags, QV4::Scope &) override final { if (watcher.wasDeleted()) return; @@ -622,7 +622,7 @@ public: protected: Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined, - QQmlPropertyData::WriteFlags flags) override Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags) override final { QQmlPropertyData *pd; QQmlPropertyData vtpd; -- cgit v1.2.3 From d8b0ad35065e7edc10140bd28f5485dd3a162ab1 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Sun, 24 Sep 2017 23:54:56 +0200 Subject: Replace Q_NULLPTR with nullptr Change-Id: I0c01862dbb475494c84e39c695cb563df8cbcfa8 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4codegen.cpp | 2 +- src/qml/jsapi/qjsengine.h | 2 +- src/qml/jsruntime/qv4identifier.cpp | 2 +- src/qml/jsruntime/qv4value_p.h | 2 +- src/qml/qml/ftw/qhashedstring_p.h | 4 +-- src/qml/qml/qqml.h | 54 ++++++++++++++++----------------- src/qml/qml/qqmlapplicationengine.h | 6 ++-- src/qml/qml/qqmlcomponent.h | 18 +++++------ src/qml/qml/qqmlcontext.h | 4 +-- src/qml/qml/qqmlengine.cpp | 8 ++--- src/qml/qml/qqmlengine.h | 2 +- src/qml/qml/qqmlexpression.h | 6 ++-- src/qml/qml/qqmlextensionplugin.h | 2 +- src/qml/qml/qqmlfileselector.h | 2 +- src/qml/qml/qqmllist.h | 34 ++++++++++----------- src/qml/qml/qqmlmetatype.cpp | 6 ++-- src/qml/qml/qqmlnotifier.cpp | 2 +- src/qml/qml/qqmlvaluetypewrapper.cpp | 4 +-- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 2 +- src/qml/util/qqmlpropertymap.h | 2 +- 20 files changed, 82 insertions(+), 82 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 5b7a7f9050..3fff29bce0 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2628,7 +2628,7 @@ bool Codegen::visit(ReturnStatement *ast) // Since we're leaving, don't let any finally statements we emit as part of the unwinding // jump to exception handlers at run-time if they throw. - IR::BasicBlock *unwindBlock = _function->newBasicBlock(/*no exception handler*/Q_NULLPTR); + IR::BasicBlock *unwindBlock = _function->newBasicBlock(/*no exception handler*/nullptr); _block->JUMP(unwindBlock); _block = unwindBlock; diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h index 41c4b81270..f92a26445f 100644 --- a/src/qml/jsapi/qjsengine.h +++ b/src/qml/jsapi/qjsengine.h @@ -119,7 +119,7 @@ private: friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *); protected: - QJSEngine(QJSEnginePrivate &dd, QObject *parent = Q_NULLPTR); + QJSEngine(QJSEnginePrivate &dd, QObject *parent = nullptr); private: QV8Engine *d; diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp index 6260fd0cc8..e35f72b820 100644 --- a/src/qml/jsruntime/qv4identifier.cpp +++ b/src/qml/jsruntime/qv4identifier.cpp @@ -152,7 +152,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const return 0; Q_ASSERT(d->entries); - uint hash = String::createHashValue(str.constData(), str.length(), Q_NULLPTR); + uint hash = String::createHashValue(str.constData(), str.length(), nullptr); uint idx = hash % d->alloc; while (1) { if (!d->entries[idx].identifier) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 50cecb6598..17d0c32853 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -601,7 +601,7 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value inline Primitive Primitive::undefinedValue() { Primitive v; - v.setM(Q_NULLPTR); + v.setM(nullptr); return v; } diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index 9ee50ec931..956805d696 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -1311,12 +1311,12 @@ bool QHashedString::compare(const char *lhs, const char *rhs, int length) quint32 QHashedString::stringHash(const QChar *data, int length) { - return QV4::String::createHashValue(data, length, Q_NULLPTR); + return QV4::String::createHashValue(data, length, nullptr); } quint32 QHashedString::stringHash(const char *data, int length) { - return QV4::String::createHashValue(data, length, Q_NULLPTR); + return QV4::String::createHashValue(data, length, nullptr); } void QHashedString::computeHash() const diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index ddb4af0b81..219df264be 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -112,10 +112,10 @@ int qmlRegisterType() qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), 0, - Q_NULLPTR, + nullptr, QString(), - Q_NULLPTR, 0, 0, Q_NULLPTR, &T::staticMetaObject, + nullptr, 0, 0, nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc(), QQmlPrivate::attachedPropertiesMetaObject(), @@ -124,9 +124,9 @@ int qmlRegisterType() QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, 0 }; @@ -146,7 +146,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), 0, - Q_NULLPTR, + nullptr, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -158,9 +158,9 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, 0 }; @@ -178,7 +178,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), 0, - Q_NULLPTR, + nullptr, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -190,9 +190,9 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, metaObjectRevision }; @@ -217,7 +217,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), 0, - Q_NULLPTR, + nullptr, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -231,7 +231,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent, &E::staticMetaObject, - Q_NULLPTR, + nullptr, 0 }; @@ -256,7 +256,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), 0, - Q_NULLPTR, + nullptr, reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -270,7 +270,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve QQmlPrivate::createParent, &E::staticMetaObject, - Q_NULLPTR, + nullptr, metaObjectRevision }; @@ -301,9 +301,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, 0 }; @@ -332,9 +332,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, metaObjectRevision }; @@ -363,9 +363,9 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, metaObjectRevision }; @@ -384,10 +384,10 @@ int qmlRegisterExtendedType() qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), 0, - Q_NULLPTR, + nullptr, QString(), - Q_NULLPTR, 0, 0, Q_NULLPTR, &T::staticMetaObject, + nullptr, 0, 0, nullptr, &T::staticMetaObject, QQmlPrivate::attachedPropertiesFunc(), QQmlPrivate::attachedPropertiesMetaObject(), @@ -398,7 +398,7 @@ int qmlRegisterExtendedType() QQmlPrivate::createParent, &E::staticMetaObject, - Q_NULLPTR, + nullptr, 0 }; @@ -437,7 +437,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::createParent, &E::staticMetaObject, - Q_NULLPTR, + nullptr, 0 }; @@ -487,7 +487,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, QQmlPrivate::StaticCastSelector::cast(), QQmlPrivate::StaticCastSelector::cast(), - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, parser, 0 @@ -583,7 +583,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, versionMajor, versionMinor, typeName, - callback, Q_NULLPTR, Q_NULLPTR, 0, 0 + callback, nullptr, nullptr, 0, 0 }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -601,7 +601,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, versionMajor, versionMinor, typeName, - Q_NULLPTR, callback, &T::staticMetaObject, qRegisterNormalizedMetaType(pointerName.constData()), 0 + nullptr, callback, &T::staticMetaObject, qRegisterNormalizedMetaType(pointerName.constData()), 0 }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h index 6c57f46c72..d0f9e6d319 100644 --- a/src/qml/qml/qqmlapplicationengine.h +++ b/src/qml/qml/qqmlapplicationengine.h @@ -53,9 +53,9 @@ class Q_QML_EXPORT QQmlApplicationEngine : public QQmlEngine { Q_OBJECT public: - QQmlApplicationEngine(QObject *parent = Q_NULLPTR); - QQmlApplicationEngine(const QUrl &url, QObject *parent = Q_NULLPTR); - QQmlApplicationEngine(const QString &filePath, QObject *parent = Q_NULLPTR); + QQmlApplicationEngine(QObject *parent = nullptr); + QQmlApplicationEngine(const QUrl &url, QObject *parent = nullptr); + QQmlApplicationEngine(const QString &filePath, QObject *parent = nullptr); ~QQmlApplicationEngine(); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index ca60f01eb5..b8cc556e4a 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -77,12 +77,12 @@ public: enum CompilationMode { PreferSynchronous, Asynchronous }; Q_ENUM(CompilationMode) - QQmlComponent(QObject *parent = Q_NULLPTR); - QQmlComponent(QQmlEngine *, QObject *parent = Q_NULLPTR); - QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = Q_NULLPTR); - QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = Q_NULLPTR); - QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = Q_NULLPTR); - QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = Q_NULLPTR); + QQmlComponent(QObject *parent = nullptr); + QQmlComponent(QQmlEngine *, QObject *parent = nullptr); + QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = nullptr); + QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = nullptr); + QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = nullptr); + QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = nullptr); virtual ~QQmlComponent(); enum Status { Null, Ready, Loading, Error }; @@ -101,12 +101,12 @@ public: QUrl url() const; - virtual QObject *create(QQmlContext *context = Q_NULLPTR); + virtual QObject *create(QQmlContext *context = nullptr); virtual QObject *beginCreate(QQmlContext *); virtual void completeCreate(); - void create(QQmlIncubator &, QQmlContext *context = Q_NULLPTR, - QQmlContext *forContext = Q_NULLPTR); + void create(QQmlIncubator &, QQmlContext *context = nullptr, + QQmlContext *forContext = nullptr); QQmlContext *creationContext() const; diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h index 781eac44fc..b2b95b7573 100644 --- a/src/qml/qml/qqmlcontext.h +++ b/src/qml/qml/qqmlcontext.h @@ -62,8 +62,8 @@ class Q_QML_EXPORT QQmlContext : public QObject Q_DECLARE_PRIVATE(QQmlContext) public: - QQmlContext(QQmlEngine *parent, QObject *objParent = Q_NULLPTR); - QQmlContext(QQmlContext *parent, QObject *objParent = Q_NULLPTR); + QQmlContext(QQmlEngine *parent, QObject *objParent = nullptr); + QQmlContext(QQmlContext *parent, QObject *objParent = nullptr); virtual ~QQmlContext(); bool isValid() const; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 5f4e291775..ea148cb29e 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -131,21 +131,21 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, 0, 0, 0, - Q_NULLPTR, + nullptr, reason, uri, versionMajor, versionMinor, qmlName, &staticMetaObject, QQmlAttachedPropertiesFunc(), - Q_NULLPTR, + nullptr, 0, 0, 0, - Q_NULLPTR, Q_NULLPTR, + nullptr, nullptr, - Q_NULLPTR, + nullptr, 0 }; diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 2bf4c0497b..b775054253 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -97,7 +97,7 @@ class Q_QML_EXPORT QQmlEngine : public QJSEngine Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath) Q_OBJECT public: - explicit QQmlEngine(QObject *p = Q_NULLPTR); + explicit QQmlEngine(QObject *p = nullptr); virtual ~QQmlEngine(); QQmlContext *rootContext() const; diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h index 5239d59c8a..e9c8770e92 100644 --- a/src/qml/qml/qqmlexpression.h +++ b/src/qml/qml/qqmlexpression.h @@ -60,8 +60,8 @@ class Q_QML_EXPORT QQmlExpression : public QObject Q_OBJECT public: QQmlExpression(); - QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = Q_NULLPTR); - explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = Q_NULLPTR, QObject * = Q_NULLPTR, QObject * = Q_NULLPTR); + QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = nullptr); + explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = nullptr, QObject * = nullptr, QObject * = nullptr); virtual ~QQmlExpression(); QQmlEngine *engine() const; @@ -84,7 +84,7 @@ public: void clearError(); QQmlError error() const; - QVariant evaluate(bool *valueIsUndefined = Q_NULLPTR); + QVariant evaluate(bool *valueIsUndefined = nullptr); Q_SIGNALS: void valueChanged(); diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h index c0915c0abe..84a46fb93e 100644 --- a/src/qml/qml/qqmlextensionplugin.h +++ b/src/qml/qml/qqmlextensionplugin.h @@ -58,7 +58,7 @@ class Q_QML_EXPORT QQmlExtensionPlugin Q_INTERFACES(QQmlExtensionInterface) Q_INTERFACES(QQmlTypesExtensionInterface) public: - explicit QQmlExtensionPlugin(QObject *parent = Q_NULLPTR); + explicit QQmlExtensionPlugin(QObject *parent = nullptr); ~QQmlExtensionPlugin(); QUrl baseUrl() const; diff --git a/src/qml/qml/qqmlfileselector.h b/src/qml/qml/qqmlfileselector.h index 03b951420e..4eaf92c918 100644 --- a/src/qml/qml/qqmlfileselector.h +++ b/src/qml/qml/qqmlfileselector.h @@ -54,7 +54,7 @@ class Q_QML_EXPORT QQmlFileSelector : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QQmlFileSelector) public: - explicit QQmlFileSelector(QQmlEngine *engine, QObject *parent = Q_NULLPTR); + explicit QQmlFileSelector(QQmlEngine *engine, QObject *parent = nullptr); ~QQmlFileSelector(); QFileSelector *selector() const Q_DECL_NOTHROW; void setSelector(QFileSelector *selector); diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h index e3955deee5..4c6ae0cb8f 100644 --- a/src/qml/qml/qqmllist.h +++ b/src/qml/qml/qqmllist.h @@ -61,20 +61,20 @@ public: typedef void (*ClearFunction)(QQmlListProperty *); QQmlListProperty() - : object(Q_NULLPTR), - data(Q_NULLPTR), - append(Q_NULLPTR), - count(Q_NULLPTR), - at(Q_NULLPTR), - clear(Q_NULLPTR), - dummy1(Q_NULLPTR), - dummy2(Q_NULLPTR) + : object(nullptr), + data(nullptr), + append(nullptr), + count(nullptr), + at(nullptr), + clear(nullptr), + dummy1(nullptr), + dummy2(nullptr) {} QQmlListProperty(QObject *o, QList &list) : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), clear(qlist_clear), - dummy1(Q_NULLPTR), - dummy2(Q_NULLPTR) + dummy1(nullptr), + dummy2(nullptr) {} QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c, AtFunction t, ClearFunction r ) @@ -84,17 +84,17 @@ public: count(c), at(t), clear(r), - dummy1(Q_NULLPTR), - dummy2(Q_NULLPTR) + dummy1(nullptr), + dummy2(nullptr) {} QQmlListProperty(QObject *o, void *d, CountFunction c, AtFunction t) : object(o), data(d), - append(Q_NULLPTR), + append(nullptr), count(c), at(t), - clear(Q_NULLPTR), - dummy1(Q_NULLPTR), - dummy2(Q_NULLPTR) + clear(nullptr), + dummy1(nullptr), + dummy2(nullptr) {} bool operator==(const QQmlListProperty &o) const { return object == o.object && @@ -140,7 +140,7 @@ class Q_QML_EXPORT QQmlListReference { public: QQmlListReference(); - QQmlListReference(QObject *, const char *property, QQmlEngine * = Q_NULLPTR); + QQmlListReference(QObject *, const char *property, QQmlEngine * = nullptr); QQmlListReference(const QQmlListReference &); QQmlListReference &operator=(const QQmlListReference &); ~QQmlListReference(); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 8e6be538ef..4f69017ff0 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -235,7 +235,7 @@ public: struct PropertyCacheByMinorVersion { - PropertyCacheByMinorVersion() : cache(Q_NULLPTR), minorVersion(-1) {} + PropertyCacheByMinorVersion() : cache(nullptr), minorVersion(-1) {} explicit PropertyCacheByMinorVersion(QQmlPropertyCache *pc, int ver) : cache(pc), minorVersion(ver) {} QQmlPropertyCachePtr cache; int minorVersion; @@ -840,7 +840,7 @@ QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersio for (int i = 0; i < propertyCaches.count(); ++i) if (propertyCaches.at(i).minorVersion == minorVersion) return propertyCaches.at(i).cache; - return Q_NULLPTR; + return nullptr; } void QQmlTypePrivate::setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache) @@ -2442,7 +2442,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches() while (it != data->propertyCaches.end()) { if ((*it)->count() == 1) { - QQmlPropertyCache *pc = Q_NULLPTR; + QQmlPropertyCache *pc = nullptr; qSwap(pc, *it); it = data->propertyCaches.erase(it); pc->release(); diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp index 938e2b77e2..e068ad174a 100644 --- a/src/qml/qml/qqmlnotifier.cpp +++ b/src/qml/qml/qqmlnotifier.cpp @@ -74,7 +74,7 @@ namespace { void QQmlNotifier::notify(QQmlData *ddata, int notifierIndex) { if (QQmlNotifierEndpoint *ep = ddata->notify(notifierIndex)) - emitNotify(ep, Q_NULLPTR); + emitNotify(ep, nullptr); } void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a) diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index ce47ab9fa9..a5cdccc97a 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -399,11 +399,11 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool); QVariant v; - void *args[] = { Q_NULLPTR, Q_NULLPTR }; + void *args[] = { nullptr, nullptr }; if (result->propType() == QMetaType::QVariant) { args[0] = &v; } else { - v = QVariant(result->propType(), static_cast(Q_NULLPTR)); + v = QVariant(result->propType(), static_cast(nullptr)); args[0] = v.data(); } metaObject->d.static_metacall(reinterpret_cast(gadget), QMetaObject::ReadProperty, index, args); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 1630efe081..25d99e0c87 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -521,7 +521,7 @@ void QtObject::method_matrix4x4(const BuiltinFunction *, Scope &scope, CallData QV4::ExecutionEngine *v4 = scope.engine; if (callData->argc == 0) { - scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR)); + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, nullptr)); return; } diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h index 8c5ecce48e..3930ac00a8 100644 --- a/src/qml/util/qqmlpropertymap.h +++ b/src/qml/util/qqmlpropertymap.h @@ -55,7 +55,7 @@ class Q_QML_EXPORT QQmlPropertyMap : public QObject { Q_OBJECT public: - explicit QQmlPropertyMap(QObject *parent = Q_NULLPTR); + explicit QQmlPropertyMap(QObject *parent = nullptr); virtual ~QQmlPropertyMap(); QVariant value(const QString &key) const; -- cgit v1.2.3