aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2017-09-04 18:21:41 +0200
committerFrederik Gladhorn <frederik.gladhorn@qt.io>2017-09-07 07:53:36 +0000
commitcf3b1bbd9ee048a28b58a55d76504b1c01e34811 (patch)
tree920fdef22725390389a8687bc3717c5e5220e32c
parenta8cff0a4dea4c5041854f9200b110e19af210a0f (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: Ice400b1c3b7bd920d855ceb1ba0d46417f50348d (cherry picked from commit 4578a92744d447222f5e22851433d5dbecc51855) Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp29
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp9
-rw-r--r--src/qml/qml/qqmltypeloader.cpp20
-rw-r--r--src/qml/qml/qqmltypeloader_p.h17
5 files changed, 62 insertions, 15 deletions
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index 245900abae..b3fa8e26f2 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -37,19 +37,32 @@
QT_BEGIN_NAMESPACE
QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
- QQmlAbstractProfilerAdapter(service), next(0)
+ QQmlAbstractProfilerAdapter(service)
{
engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
+ init(engine->profiler);
+}
+
+QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlTypeLoader *loader) :
+ QQmlAbstractProfilerAdapter(service)
+{
+ loader->enableProfiler();
+ init(loader->profiler());
+}
+
+void QQmlProfilerAdapter::init(QQmlProfiler *profiler)
+{
+ next = 0;
+ connect(this, SIGNAL(profilingEnabled(quint64)), profiler, SLOT(startProfiling(quint64)));
connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
- engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
+ profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
- engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ profiler, SLOT(stopProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
- engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)),
+ profiler, SLOT(setTimer(QElapsedTimer)));
+ connect(profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)),
this, SLOT(receiveData(QVector<QQmlProfilerData>)));
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index eceb58ce3a..8eb61f9744 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -54,12 +54,14 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
Q_OBJECT
public:
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
+ QQmlProfilerAdapter(QQmlProfilerService *service, QQmlTypeLoader *loader);
qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
public slots:
void receiveData(const QVector<QQmlProfilerData> &new_data);
private:
+ void init(QQmlProfiler *profiler);
QVector<QQmlProfilerData> data;
int next;
};
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index a5ee494ced..930a5d37d8 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -98,9 +98,14 @@ void QQmlProfilerServiceImpl::engineAboutToBeAdded(QQmlEngine *engine)
"QML profilers have to be added from the engine thread");
QMutexLocker lock(&m_configMutex);
- QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
- QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, enginePrivate);
+ QQmlProfilerAdapter *compileAdapter
+ = new QQmlProfilerAdapter(this, &(enginePrivate->typeLoader));
+ QV4ProfilerAdapter *v4Adapter
+ = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
addEngineProfiler(qmlAdapter, engine);
+ addEngineProfiler(compileAdapter, engine);
addEngineProfiler(v4Adapter, engine);
QQmlConfigurableDebugService<QQmlProfilerService>::engineAboutToBeAdded(engine);
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 6480420212..074f760a36 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -647,8 +647,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->url());
+ QQmlCompilingProfiler prof(typeLoader()->profiler(), blob->url());
m_inCallback = true;
@@ -901,6 +900,12 @@ void QQmlTypeLoader::invalidate()
m_networkReplies.clear();
}
+void QQmlTypeLoader::enableProfiler()
+{
+ Q_ASSERT(!m_profiler);
+ m_profiler = new QQmlProfiler;
+}
+
void QQmlTypeLoader::lock()
{
m_thread->lock();
@@ -1216,7 +1221,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
{
QML_MEMORY_SCOPE_URL(blob->url());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+ QQmlCompilingProfiler prof(profiler(), blob->url());
blob->m_inCallback = true;
@@ -1236,7 +1241,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
QML_MEMORY_SCOPE_URL(blob->url());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+ QQmlCompilingProfiler prof(profiler(), blob->url());
blob->m_inCallback = true;
@@ -1594,6 +1599,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(0),
+#endif
m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD)
{
}
@@ -1610,6 +1618,10 @@ QQmlTypeLoader::~QQmlTypeLoader()
clearCache();
invalidate();
+
+#ifndef QT_NO_QML_DEBUGGER
+ delete m_profiler;
+#endif
}
QQmlImportDatabase *QQmlTypeLoader::importDatabase()
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index f565bcd31f..5095aa6bcf 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -74,6 +74,7 @@ class QQmlComponentPrivate;
class QQmlTypeData;
class QQmlTypeLoader;
class QQmlExtensionInterface;
+class QQmlProfiler;
namespace QmlIR {
struct Document;
@@ -211,7 +212,7 @@ private:
class QQmlTypeLoaderThread;
-class Q_AUTOTEST_EXPORT QQmlTypeLoader
+class Q_QML_PRIVATE_EXPORT QQmlTypeLoader
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
public:
@@ -311,6 +312,15 @@ public:
void initializeEngine(QQmlExtensionInterface *, const char *);
void invalidate();
+#ifdef QT_NO_QML_DEBUGGER
+ QQmlProfiler *profiler() const { return 0; }
+ void enableProfiler() {}
+#else
+ QQmlProfiler *profiler() const { return m_profiler; }
+ void enableProfiler();
+#endif // QT_NO_QML_DEBUGGER
+
+
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoaderThread;
@@ -356,6 +366,11 @@ private:
QQmlEngine *m_engine;
QQmlTypeLoaderThread *m_thread;
+
+#ifndef QT_NO_QML_DEBUGGER
+ QQmlProfiler *m_profiler;
+#endif
+
NetworkReplies m_networkReplies;
TypeCache m_typeCache;
int m_typeCacheTrimThreshold;