diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2017-09-04 18:21:41 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2017-09-05 13:08:08 +0000 |
commit | 4578a92744d447222f5e22851433d5dbecc51855 (patch) | |
tree | 4bb8ffe40faa77177261cfa211cd039c89f9d2b5 /src | |
parent | 560557c5d7d6b48dada2c9966577c718eab7d19d (diff) |
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 <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp | 32 | ||||
-rw-r--r-- | src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h | 2 | ||||
-rw-r--r-- | src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 15 |
5 files changed, 54 insertions, 16 deletions
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index 510c745d4e..d676731ba7 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -44,24 +44,36 @@ QT_BEGIN_NAMESPACE -QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) : - next(0) +QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) { - setService(service); engine->profiler = new QQmlProfiler; + init(service, engine->profiler); +} + +QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlTypeLoader *loader) +{ + QQmlProfiler *profiler = new QQmlProfiler; + loader->setProfiler(profiler); + init(service, profiler); +} + +void QQmlProfilerAdapter::init(QQmlProfilerService *service, QQmlProfiler *profiler) +{ + next = 0; + setService(service); connect(this, &QQmlProfilerAdapter::profilingEnabled, - engine->profiler, &QQmlProfiler::startProfiling); + profiler, &QQmlProfiler::startProfiling); connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting, - engine->profiler, &QQmlProfiler::startProfiling, Qt::DirectConnection); + profiler, &QQmlProfiler::startProfiling, Qt::DirectConnection); connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled, - engine->profiler, &QQmlProfiler::stopProfiling); + profiler, &QQmlProfiler::stopProfiling); connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting, - engine->profiler, &QQmlProfiler::stopProfiling, Qt::DirectConnection); + profiler, &QQmlProfiler::stopProfiling, Qt::DirectConnection); connect(this, &QQmlAbstractProfilerAdapter::dataRequested, - engine->profiler, &QQmlProfiler::reportData); + profiler, &QQmlProfiler::reportData); connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown, - engine->profiler, &QQmlProfiler::setTimer); - connect(engine->profiler, &QQmlProfiler::dataReady, + profiler, &QQmlProfiler::setTimer); + connect(profiler, &QQmlProfiler::dataReady, this, &QQmlProfilerAdapter::receiveData); } diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h index 1fee5c389f..7531cd1dff 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h @@ -60,6 +60,7 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter { Q_OBJECT public: QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine); + QQmlProfilerAdapter(QQmlProfilerService *service, QQmlTypeLoader *loader); qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) Q_DECL_OVERRIDE; @@ -67,6 +68,7 @@ public: const QQmlProfiler::LocationHash &locations); private: + void init(QQmlProfilerService *service, QQmlProfiler *profiler); QVector<QQmlProfilerData> data; QQmlProfiler::LocationHash locations; int next; diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp index edeb364f60..4176ede40e 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp @@ -119,9 +119,12 @@ void QQmlProfilerServiceImpl::engineAboutToBeAdded(QJSEngine *engine) QMutexLocker lock(&m_configMutex); if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine)) { - QQmlProfilerAdapter *qmlAdapter = - new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(qmlEngine)); + QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(qmlEngine); + QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, enginePrivate); addEngineProfiler(qmlAdapter, engine); + QQmlProfilerAdapter *compileAdapter + = new QQmlProfilerAdapter(this, &(enginePrivate->typeLoader)); + addEngineProfiler(compileAdapter, engine); } QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle())); addEngineProfiler(v4Adapter, engine); 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 |