aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@digia.com>2014-01-24 12:44:49 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-15 22:37:48 +0100
commit72420889aa54342da4472683e67e2c70b76a170f (patch)
tree3bbbb3a3f7b3286cb40f01763c42886bfd265500
parent9424383e6d0ea1dd02dcf1070259e21550da692a (diff)
Add dedicated QML profiler and adapter
The remaining "profiling" parts of the QML profiler service are engine specific and are best accessed through their own adapter. Change-Id: Idb763104bdd80e4dabdf132ec1a496b9bc9f6f46 Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r--src/qml/debugger/debugger.pri6
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp205
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h368
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp180
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h328
-rw-r--r--src/qml/qml/qqmlbinding.cpp6
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp9
-rw-r--r--src/qml/qml/qqmlengine.cpp8
-rw-r--r--src/qml/qml/qqmlengine_p.h3
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/qml/qml/qqmlvme.cpp20
-rw-r--r--src/qml/qml/qqmlvme_p.h2
12 files changed, 611 insertions, 528 deletions
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri
index 514d8cdce2..27b72a320c 100644
--- a/src/qml/debugger/debugger.pri
+++ b/src/qml/debugger/debugger.pri
@@ -10,7 +10,8 @@ SOURCES += \
$$PWD/qqmlconfigurabledebugservice.cpp \
$$PWD/qqmlenginecontrolservice.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
- $$PWD/qv4profileradapter.cpp
+ $$PWD/qv4profileradapter.cpp \
+ $$PWD/qqmlprofiler.cpp
HEADERS += \
$$PWD/qqmldebugservice_p.h \
@@ -31,4 +32,5 @@ HEADERS += \
$$PWD/qqmlenginecontrolservice_p.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
- $$PWD/qv4profileradapter_p.h
+ $$PWD/qv4profileradapter_p.h \
+ $$PWD/qqmlprofiler_p.h
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
new file mode 100644
index 0000000000..f92d76cf5d
--- /dev/null
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlprofiler_p.h"
+#include "qqmlprofilerservice_p.h"
+#include "qqmldebugservice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+// (see tst_qqmldebugtrace::trace() benchmark)
+void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
+{
+ QByteArray data;
+ Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
+ for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
+ if ((messageType & (1 << decodedMessageType)) == 0)
+ continue;
+
+ for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
+ if ((detailType & (1 << decodedDetailType)) == 0)
+ continue;
+
+ //### using QDataStream is relatively expensive
+ QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+ ds << time << decodedMessageType << decodedDetailType;
+
+ switch (decodedMessageType) {
+ case QQmlProfilerDefinitions::RangeStart:
+ if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding)
+ ds << QQmlProfilerDefinitions::QmlBinding;
+ break;
+ case QQmlProfilerDefinitions::RangeData:
+ ds << detailString;
+ break;
+ case QQmlProfilerDefinitions::RangeLocation:
+ ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y;
+ break;
+ case QQmlProfilerDefinitions::RangeEnd: break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
+ }
+ messages << data;
+ data.clear();
+ }
+ }
+}
+
+QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) :
+ QQmlAbstractProfilerAdapter(service)
+{
+ engine->enableProfiler();
+ connect(this, SIGNAL(profilingEnabled()), engine->profiler, SLOT(startProfiling()));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting()),
+ engine->profiler, SLOT(startProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
+ connect(this, SIGNAL(profilingDisabledWhileWaiting()),
+ engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(referenceTimeKnown(const QElapsedTimer &)),
+ engine->profiler, SLOT(setTimer(const QElapsedTimer &)));
+ connect(engine->profiler, SIGNAL(dataReady(const QList<QQmlProfilerData> &)),
+ this, SLOT(receiveData(const QList<QQmlProfilerData> &)));
+}
+
+qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+ while (!data.empty() && data.front().time <= until) {
+ data.front().toByteArrays(messages);
+ data.pop_front();
+ }
+ return data.empty() ? -1 : data.front().time;
+}
+
+void QQmlProfilerAdapter::receiveData(const QList<QQmlProfilerData> &new_data)
+{
+ data = new_data;
+ service->dataReady(this);
+}
+
+
+QQmlProfiler::QQmlProfiler() : enabled(false)
+{
+ static int metatype = qRegisterMetaType<QList<QQmlProfilerData> >();
+ Q_UNUSED(metatype);
+ m_timer.start();
+}
+
+void QQmlProfiler::startProfiling()
+{
+ enabled = true;
+}
+
+void QQmlProfiler::stopProfiling()
+{
+ enabled = false;
+ reportData();
+ m_data.clear();
+}
+
+void QQmlProfiler::reportData()
+{
+ QList<QQmlProfilerData> result;
+ result.reserve(m_data.size());
+ for (int i = 0; i < m_data.size(); ++i)
+ result.append(m_data[i]);
+ emit dataReady(result);
+}
+
+/*!
+ * \fn void QQmlVmeProfiler::Data::clear()
+ * Resets the profiling data to defaults.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::startBackground(const QString &typeName)
+ * If profiling is enabled clears the current range data, then stops the
+ * profiler previously running in the foreground if any, then starts a new one
+ * in the background, setting the given typeName. \a typeName is the type of
+ * object being created.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::start(const QString &typeName, const QUrl &url, int line, int column)
+ * If profiling is enabled clears the current range data, then stops the
+ * profiler previously running in the foreground if any, then starts a new one
+ * in the foreground, setting the given location. \a url is the URL of
+ * file being executed, \line line is the current line in in that file, and
+ * \a column is the current column in that file.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::pop()
+ * Stops the currently running profiler, if any, then retrieves an old one from the stack
+ * of paused profilers and starts that if possible.
+ */
+
+/*!
+ * \fn void QQmlVmeProfiler::push()
+ * Pushes the currently running profiler on the stack of paused profilers. Note: The profiler
+ * isn't paused here. That's a separate step. If it's never paused, but pop()'ed later that
+ * won't do any harm, though.
+ */
+
+/*!
+ * \fn void QQmlVmeProfiler::clear()
+ * Stops the currently running (foreground and background) profilers and removes all saved
+ * data about paused profilers.
+ */
+
+/*!
+ * \fn void QQmlVmeProfiler::stop()
+ * Stop profiler running in the foreground, if any.
+ */
+
+/*!
+ * \fn bool QQmlVmeProfiler::foreground(const QUrl &url, int line, int column)
+ * Stops the profiler currently running in the foreground, if any and puts the
+ * next profiler from the background in its place if there are any profilers in
+ * the background. Additionally the rangeLocation is set. \a url is the URL of
+ * file being executed, \line line is the current line in in that file, and
+ * \a column is the current column in that file.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
new file mode 100644
index 0000000000..ca464e86a3
--- /dev/null
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROFILER_P_H
+#define QQMLPROFILER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4function_p.h>
+#include <private/qqmlboundsignal_p.h>
+#include "qqmlprofilerdefinitions_p.h"
+#include "qqmlabstractprofileradapter_p.h"
+
+#include <QUrl>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+#define Q_QML_PROFILE_IF_ENABLED(profiler, Code)\
+ if (profiler && profiler->enabled) {\
+ Code;\
+ } else\
+ (void)0
+
+#define Q_QML_PROFILE(profiler, Method)\
+ Q_QML_PROFILE_IF_ENABLED(profiler, profiler->Method)
+
+// This struct is somewhat dangerous to use:
+// The messageType is a bit field. You can pack multiple messages into
+// one object, e.g. RangeStart and RangeLocation. Each one will be read
+// independently by toByteArrays. Thus you can only pack messages if their data
+// doesn't overlap. It's up to you to figure that out.
+struct Q_AUTOTEST_EXPORT QQmlProfilerData
+{
+ QQmlProfilerData() {}
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url,
+ int x = 0, int y = 0) :
+ time(time), messageType(messageType), detailType(detailType), detailUrl(url),
+ x(x), y(y) {}
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
+ int x = 0, int y = 0) :
+ time(time), messageType(messageType), detailType(detailType),detailString(str),
+ x(x), y(y) {}
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
+ const QUrl &url, int x = 0, int y = 0) :
+ time(time), messageType(messageType), detailType(detailType), detailString(str),
+ detailUrl(url), x(x), y(y) {}
+
+
+ QQmlProfilerData(qint64 time, int messageType, int detailType) :
+ time(time), messageType(messageType), detailType(detailType) {}
+
+
+ qint64 time;
+ int messageType; //bit field of QQmlProfilerService::Message
+ int detailType;
+
+ QString detailString; //used by RangeData and possibly by RangeLocation
+ QUrl detailUrl; //used by RangeLocation, overrides detailString
+
+ int x; //used by RangeLocation
+ int y; //used by RangeLocation
+
+ void toByteArrays(QList<QByteArray> &messages) const;
+};
+
+Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
+
+class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
+ Q_OBJECT
+public:
+ void startBinding(const QString &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation), 1 << Binding,
+ fileName, line, column));
+ }
+
+ // Have toByteArrays() construct another RangeData event from the same QString later.
+ // This is somewhat pointless but important for backwards compatibility.
+ void startCompiling(const QString &name)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
+ 1 << Compiling, name, 1, 1));
+ }
+
+ void startHandlingSignal(const QString &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal,
+ fileName, line, column));
+ }
+
+ void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
+ 1 << Creating, typeName, fileName, line, column));
+ }
+
+ void startCreating(const QString &typeName)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeData),
+ 1 << Creating, typeName));
+ }
+
+ void creatingLocation(const QUrl &fileName, int line, int column)
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeLocation, 1 << Creating,
+ fileName, line, column));
+ }
+
+ template<RangeType Range>
+ void endRange()
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range));
+ }
+
+ QQmlProfiler();
+
+ bool enabled;
+
+public slots:
+ void startProfiling();
+ void stopProfiling();
+ void reportData();
+ void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
+
+signals:
+ void dataReady(const QList<QQmlProfilerData> &);
+
+protected:
+ QElapsedTimer m_timer;
+ QVarLengthArray<QQmlProfilerData> m_data;
+};
+
+class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
+ Q_OBJECT
+public:
+ QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+public slots:
+ void receiveData(const QList<QQmlProfilerData> &new_data);
+
+private:
+ QList<QQmlProfilerData> data;
+};
+
+//
+// RAII helper structs
+//
+
+struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
+ QQmlProfiler *profiler;
+ QQmlProfilerHelper(QQmlProfiler *profiler) : profiler(profiler) {}
+};
+
+struct QQmlBindingProfiler : public QQmlProfilerHelper {
+ QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) :
+ QQmlProfilerHelper(profiler)
+ {
+ Q_QML_PROFILE(profiler, startBinding(url, line, column));
+ }
+
+ ~QQmlBindingProfiler()
+ {
+ Q_QML_PROFILE(profiler, endRange<Binding>());
+ }
+};
+
+struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
+ QQmlHandlingSignalProfiler(QQmlProfiler *profiler, QQmlBoundSignalExpression *expression) :
+ QQmlProfilerHelper(profiler)
+ {
+ Q_QML_PROFILE_IF_ENABLED(profiler, {
+ QV4::Function *function;
+ if (expression->sourceFile().isEmpty() && (function = expression->function())) {
+ profiler->startHandlingSignal(
+ function->sourceFile(), function->compiledFunction->location.line,
+ function->compiledFunction->location.column);
+
+ } else {
+ profiler->startHandlingSignal(
+ expression->sourceFile(), expression->lineNumber(),
+ expression->columnNumber());
+ }
+ });
+ }
+
+ ~QQmlHandlingSignalProfiler()
+ {
+ Q_QML_PROFILE(profiler, endRange<QQmlProfiler::HandlingSignal>());
+ }
+};
+
+struct QQmlCompilingProfiler : public QQmlProfilerHelper {
+ QQmlCompilingProfiler(QQmlProfiler *profiler, const QString &name) :
+ QQmlProfilerHelper(profiler)
+ {
+ Q_QML_PROFILE(profiler, startCompiling(name));
+ }
+
+ ~QQmlCompilingProfiler()
+ {
+ Q_QML_PROFILE(profiler, endRange<Compiling>());
+ }
+};
+
+#define Q_QML_VME_PROFILE(profiler, Method) Q_QML_PROFILE_IF_ENABLED(profiler.profiler, profiler.Method)
+
+struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
+public:
+
+ struct Data {
+ Data() : line(0), column(0) {}
+ QUrl url;
+ int line;
+ int column;
+ QString typeName;
+ };
+
+ QQmlVmeProfiler() : profiler(0), running(false) {}
+
+ void clear(bool stopProfiling = false)
+ {
+ ranges.clear();
+ if (running)
+ profiler->endRange<Creating>();
+ for (int i = 0; i < backgroundRanges.count(); ++i) {
+ profiler->endRange<Creating>();
+ }
+ backgroundRanges.clear();
+ running = false;
+ if (stopProfiling) profiler = 0;
+ }
+
+ void startBackground(const QString &typeName)
+ {
+ if (running) {
+ profiler->endRange<Creating>();
+ running = false;
+ }
+ profiler->startCreating(typeName);
+ backgroundRanges.push(typeName);
+ }
+
+ void start(const QString &typeName, const QUrl &url, int line, int column)
+ {
+ switchRange();
+ setCurrentRange(typeName, url, line, column);
+ profiler->startCreating(typeName, url, line, column);
+ }
+
+ void stop()
+ {
+ if (running) {
+ profiler->endRange<Creating>();
+ running = false;
+ }
+ }
+
+ void pop()
+ {
+ if (ranges.count() > 0) {
+ switchRange();
+ currentRange = ranges.pop();
+ profiler->startCreating(currentRange.typeName, currentRange.url,
+ currentRange.line, currentRange.column);
+ }
+ }
+
+ void push()
+ {
+ if (running)
+ ranges.push(currentRange);
+ }
+
+ void foreground(const QUrl &url, int line, int column)
+ {
+ if (backgroundRanges.count() > 0) {
+ switchRange();
+ setCurrentRange(backgroundRanges.pop(), url, line, column);
+ profiler->creatingLocation(url, line, column);
+ }
+ }
+
+ QQmlProfiler *profiler;
+
+private:
+
+ void switchRange()
+ {
+ if (running)
+ profiler->endRange<Creating>();
+ else
+ running = true;
+ }
+
+ void setCurrentRange(const QString &typeName, const QUrl &url, int line, int column)
+ {
+ currentRange.typeName = typeName;
+ currentRange.url = url;
+ currentRange.line = line;
+ currentRange.column = column;
+ }
+
+ Data currentRange;
+ QStack<Data> ranges;
+ QStack<QString> backgroundRanges;
+ bool running;
+};
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QList<QQmlProfilerData>)
+
+#endif // QQMLPROFILER_P_H
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index e4620a282a..5500b8f22c 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -42,6 +42,7 @@
#include "qqmlprofilerservice_p.h"
#include "qqmldebugserver_p.h"
#include "qv4profileradapter_p.h"
+#include "qqmlprofiler_p.h"
#include <private/qqmlengine_p.h>
#include <QtCore/qdatastream.h>
@@ -52,87 +53,7 @@
QT_BEGIN_NAMESPACE
-// instance will be set, unset in constructor. Allows static methods to be inlined.
-QQmlProfilerService *QQmlProfilerService::m_instance = 0;
Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance)
-bool QQmlProfilerService::enabled = false;
-
-// convert to QByteArrays that can be sent to the debug client
-// use of QDataStream can skew results
-// (see tst_qqmldebugtrace::trace() benchmark)
-void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
-{
- QByteArray data;
- Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
- for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
- if ((messageType & (1 << decodedMessageType)) == 0)
- continue;
-
- for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
- if ((detailType & (1 << decodedDetailType)) == 0)
- continue;
-
- //### using QDataStream is relatively expensive
- QQmlDebugStream ds(&data, QIODevice::WriteOnly);
- ds << time << decodedMessageType << decodedDetailType;
-
- switch (decodedMessageType) {
- case QQmlProfilerService::Event:
- if (decodedDetailType == (int)QQmlProfilerService::AnimationFrame)
- ds << framerate << count;
- break;
- case QQmlProfilerService::RangeStart:
- if (decodedDetailType == (int)QQmlProfilerService::Binding)
- ds << bindingType;
- break;
- case QQmlProfilerService::RangeData:
- ds << detailString;
- break;
- case QQmlProfilerService::RangeLocation:
- ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y;
- break;
- case QQmlProfilerService::RangeEnd: break;
- case QQmlProfilerService::PixmapCacheEvent:
- ds << detailUrl.toString();
- switch (decodedDetailType) {
- case QQmlProfilerService::PixmapSizeKnown: ds << x << y; break;
- case QQmlProfilerService::PixmapReferenceCountChanged: ds << count; break;
- case QQmlProfilerService::PixmapCacheCountChanged: ds << count; break;
- default: break;
- }
- break;
- case QQmlProfilerService::SceneGraphFrame:
- switch (decodedDetailType) {
- // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
- case QQmlProfilerService::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
- // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
- case QQmlProfilerService::SceneGraphAdaptationLayerFrame: ds << (int)subtime_1 << subtime_2 << subtime_3; break;
- // ContextFrame: compiling material time
- case QQmlProfilerService::SceneGraphContextFrame: ds << subtime_1; break;
- // RenderLoop: syncTime, renderTime, swapTime
- case QQmlProfilerService::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break;
- // TexturePrepare: bind, convert, swizzle, upload, mipmap
- case QQmlProfilerService::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break;
- // TextureDeletion: deletionTime
- case QQmlProfilerService::SceneGraphTextureDeletion: ds << subtime_1; break;
- // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
- case QQmlProfilerService::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
- // WindowsRenderLoop: GL time, make current time, SceneGraph time
- case QQmlProfilerService::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break;
- // WindowsAnimations: update time
- case QQmlProfilerService::SceneGraphWindowsAnimations: ds << subtime_1; break;
- // WindowsRenderWindow: polish time; always comes packed after a RenderLoop
- case QQmlProfilerService::SceneGraphWindowsPolishFrame: ds << subtime_4; break;
- default:break;
- }
- break;
- case QQmlProfilerService::Complete: break;
- }
- messages << data;
- data.clear();
- }
- }
-}
QQmlProfilerService::QQmlProfilerService()
: QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1)
@@ -149,8 +70,6 @@ QQmlProfilerService::~QQmlProfilerService()
{
// No need to lock here. If any engine or global profiler is still trying to register at this
// point we have a nasty bug anyway.
- enabled = false;
- m_instance = 0;
qDeleteAll(m_engineProfilers.keys());
qDeleteAll(m_globalProfilers);
}
@@ -190,8 +109,7 @@ void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler)
QQmlProfilerService *QQmlProfilerService::instance()
{
// just make sure that the service is properly registered
- m_instance = profilerInstance();
- return m_instance;
+ return profilerInstance();
}
void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine)
@@ -199,7 +117,7 @@ void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine)
Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread");
QMutexLocker lock(configMutex());
- QQmlProfiler *qmlAdapter = new QQmlProfiler(this);
+ QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine));
QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle()));
addEngineProfiler(qmlAdapter, engine);
addEngineProfiler(v4Adapter, engine);
@@ -329,43 +247,6 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine)
}
}
-QQmlProfiler::QQmlProfiler(QQmlProfilerService *service) :
- QQmlAbstractProfilerAdapter(service), next(0)
-{
- connect(this, SIGNAL(profilingEnabled()), this, SLOT(startProfiling()));
- connect(this, SIGNAL(profilingEnabledWhileWaiting()), this, SLOT(startProfiling()),
- Qt::DirectConnection);
- connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfiling()));
- connect(this, SIGNAL(profilingDisabledWhileWaiting()), this, SLOT(stopProfiling()),
- Qt::DirectConnection);
-}
-
-qint64 QQmlProfiler::sendMessages(qint64 until, QList<QByteArray> &messages)
-{
- QMutexLocker lock(&QQmlProfilerService::instance()->m_dataMutex);
- QVector<QQmlProfilerData> *data = &(QQmlProfilerService::instance()->m_data);
- while (next < data->size() && data->at(next).time <= until) {
- data->at(next++).toByteArrays(messages);
- }
- return next < data->size() ? data->at(next).time : -1;
-}
-
-void QQmlProfiler::startProfiling()
-{
- if (!QQmlProfilerService::enabled) {
- next = 0;
- service->m_data.clear();
- QQmlProfilerService::enabled = true;
- }
-}
-
-void QQmlProfiler::stopProfiling()
-{
- next = 0;
- QQmlProfilerService::enabled = false;
- service->dataReady(this);
-}
-
/*
Send the queued up messages.
*/
@@ -458,59 +339,4 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
stopWaiting();
}
-/*!
- * \fn void QQmlVmeProfiler::Data::clear()
- * Resets the profiling data to defaults.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::startBackground(const QString &typeName)
- * If profiling is enabled clears the current range data, then stops the
- * profiler previously running in the foreground if any, then starts a new one
- * in the background, setting the given typeName. \a typeName is the type of
- * object being created.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::start(const QString &typeName, const QUrl &url, int line, int column)
- * If profiling is enabled clears the current range data, then stops the
- * profiler previously running in the foreground if any, then starts a new one
- * in the foreground, setting the given location. \a url is the URL of
- * file being executed, \line line is the current line in in that file, and
- * \a column is the current column in that file.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::pop()
- * Stops the currently running profiler, if any, then retrieves an old one from the stack
- * of paused profilers and starts that if possible.
- */
-
-/*!
- * \fn void QQmlVmeProfiler::push()
- * Pushes the currently running profiler on the stack of paused profilers. Note: The profiler
- * isn't paused here. That's a separate step. If it's never paused, but pop()'ed later that
- * won't do any harm, though.
- */
-
-/*!
- * \fn void QQmlVmeProfiler::clear()
- * Stops the currently running (foreground and background) profilers and removes all saved
- * data about paused profilers.
- */
-
-/*!
- * \fn void QQmlVmeProfiler::stop()
- * Stop profiler running in the foreground, if any.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::foreground(const QUrl &url, int line, int column)
- * Stops the profiler currently running in the foreground, if any and puts the
- * next profiler from the background in its place if there are any profilers in
- * the background. Additionally the rangeLocation is set. \a url is the URL of
- * file being executed, \line line is the current line in in that file, and
- * \a column is the current column in that file.
- */
-
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index a5d85a76e6..9e05424ce1 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -58,7 +58,6 @@
#include "qqmlabstractprofileradapter_p.h"
#include <private/qqmlboundsignal_p.h>
-#include <private/qv4function_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetaobject.h>
@@ -67,94 +66,8 @@
#include <QtCore/qstringbuilder.h>
#include <QtCore/qwaitcondition.h>
-#define Q_QML_PROFILE_IF_ENABLED(Code)\
- if (QQmlProfilerService::enabled) {\
- Code;\
- } else\
- (void)0
-
-#define Q_QML_PROFILE(Method)\
- Q_QML_PROFILE_IF_ENABLED(QQmlProfilerService::Method)
-
QT_BEGIN_NAMESPACE
-// This struct is somewhat dangerous to use:
-// You can save values either with 32 or 64 bit precision. toByteArrays will
-// guess the precision from messageType. If you state the wrong messageType
-// you will get undefined results.
-// The messageType is itself a bit field. You can pack multiple messages into
-// one object, e.g. RangeStart and RangeLocation. Each one will be read
-// independently by toByteArrays. Thus you can only pack messages if their data
-// doesn't overlap. Again, it's up to you to figure that out.
-struct Q_AUTOTEST_EXPORT QQmlProfilerData
-{
- QQmlProfilerData() {}
-
- QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url,
- int x = 0, int y = 0, int framerate = 0, int count = 0, int bindingType = 0) :
- time(time), messageType(messageType), detailType(detailType), detailUrl(url),
- x(x), y(y), framerate(framerate), count(count), bindingType(bindingType) {}
-
- QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
- int x = 0, int y = 0, int framerate = 0, int count = 0, int bindingType = 0) :
- time(time), messageType(messageType), detailType(detailType),detailString(str),
- x(x), y(y), framerate(framerate), count(count), bindingType(bindingType) {}
-
- QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
- const QUrl &url, int x = 0, int y = 0, int framerate = 0, int count = 0,
- int bindingType = 0) :
- time(time), messageType(messageType), detailType(detailType), detailString(str),
- detailUrl(url), x(x), y(y), framerate(framerate), count(count), bindingType(bindingType) {}
-
-
- QQmlProfilerData(qint64 time, int messageType, int detailType) :
- time(time), messageType(messageType), detailType(detailType) {}
-
- // Special ctor for scenegraph frames. Note that it's missing the QString/QUrl params.
- // This is slightly ugly, but makes it easier to disambiguate between int and qint64 params.
- QQmlProfilerData(qint64 time, int messageType, int detailType,
- qint64 d1, qint64 d2, qint64 d3, qint64 d4, qint64 d5) :
- time(time), messageType(messageType), detailType(detailType),
- subtime_1(d1), subtime_2(d2), subtime_3(d3), subtime_4(d4), subtime_5(d5) {}
-
-
- qint64 time;
- int messageType; //bit field of QQmlProfilerService::Message
- int detailType;
-
- QString detailString; //used by RangeData and possibly by RangeLocation
- QUrl detailUrl; //used by RangeLocation, overrides detailString
-
- union {
- qint64 subtime_1;
- int x; //used by RangeLocation and for pixmaps
- };
-
- union {
- qint64 subtime_2;
- int y; //used by RangeLocation and for pixmaps
- };
-
- union {
- qint64 subtime_3;
- int framerate; //used by animation events
- };
-
- union {
- qint64 subtime_4;
- int count; //used by animation events and for pixmaps
- };
-
- union {
- qint64 subtime_5;
- int bindingType;
- };
-
- void toByteArrays(QList<QByteArray> &messages) const;
-};
-
-Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
-
class QUrl;
class QQmlEngine;
@@ -176,8 +89,6 @@ public:
void startProfiling(QQmlEngine *engine);
void stopProfiling(QQmlEngine *engine);
- qint64 timestamp() {return m_timer.nsecsElapsed();}
-
QQmlProfilerService();
~QQmlProfilerService();
@@ -189,254 +100,15 @@ protected:
private:
- static void startBinding(const QString &fileName, int line, int column, BindingType bindingType)
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(),
- (1 << RangeStart | 1 << RangeLocation),
- 1 << Binding, fileName, line, column, 0, 0,
- bindingType));
- }
-
- // Have toByteArrays() construct another RangeData event from the same QString later.
- // This is somewhat pointless but important for backwards compatibility.
- static void startCompiling(const QString &name)
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(),
- (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), 1 << Compiling,
- name, 1, 1, 0, 0, QmlBinding));
- }
-
- static void startHandlingSignal(const QString &fileName, int line, int column)
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(),
- (1 << RangeStart | 1 << RangeLocation),
- 1 << HandlingSignal, fileName, line, column, 0, 0,
- QmlBinding));
- }
-
- static void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(),
- (1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
- 1 << Creating, typeName, fileName, line, column,
- 0, 0, QmlBinding));
- }
-
- static void startCreating(const QString &typeName)
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(),
- (1 << RangeStart | 1 << RangeData), 1 << Creating,
- typeName, 0, 0, 0, 0, QmlBinding));
- }
-
- static void creatingLocation(const QUrl &fileName, int line, int column)
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << RangeLocation,
- 1 << Creating, fileName, line, column));
- }
-
- template<RangeType Range>
- static void endRange()
- {
- m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << RangeEnd,
- 1 << Range));
- }
-
void sendMessages();
void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine);
- void processMessage(const QQmlProfilerData &message)
- {
- QMutexLocker locker(&m_dataMutex);
- m_data.append(message);
- }
-
-public:
- static bool enabled;
-private:
QElapsedTimer m_timer;
- QVector<QQmlProfilerData> m_data;
- QMutex m_dataMutex;
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
QMultiHash<QQmlEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
QList<QQmlEngine *> m_stoppingEngines;
QMultiMap<qint64, QQmlAbstractProfilerAdapter *> m_startTimes;
-
- static QQmlProfilerService *m_instance;
-
- friend struct QQmlBindingProfiler;
- friend struct QQmlHandlingSignalProfiler;
- friend struct QQmlVmeProfiler;
- friend struct QQmlCompilingProfiler;
- friend class QQmlProfiler;
-};
-
-// Temporary shim around QQmlProfilerService to make it look like a QQmlAbstractProfilerAdapter.
-class QQmlProfiler : public QQmlAbstractProfilerAdapter {
- Q_OBJECT
-public:
- QQmlProfiler(QQmlProfilerService *service);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
-
-public slots:
- void startProfiling();
- void stopProfiling();
-private:
- int next;
-};
-
-//
-// RAII helper structs
-//
-
-struct QQmlBindingProfiler {
- QQmlBindingProfiler(const QString &url, int line, int column, QQmlProfilerService::BindingType bindingType)
- {
- Q_QML_PROFILE(startBinding(url, line, column, bindingType));
- }
-
- ~QQmlBindingProfiler()
- {
- Q_QML_PROFILE(endRange<QQmlProfilerService::Binding>());
- }
-};
-
-struct QQmlHandlingSignalProfiler {
- QQmlHandlingSignalProfiler(QQmlBoundSignalExpression *expression)
- {
- Q_QML_PROFILE_IF_ENABLED({
- QV4::Function *function;
- if (expression->sourceFile().isEmpty() && (function = expression->function())) {
- QQmlProfilerService::startHandlingSignal(
- function->sourceFile(), function->compiledFunction->location.line,
- function->compiledFunction->location.column);
-
- } else {
- QQmlProfilerService::startHandlingSignal(
- expression->sourceFile(), expression->lineNumber(),
- expression->columnNumber());
- }
- });
- }
-
- ~QQmlHandlingSignalProfiler()
- {
- Q_QML_PROFILE(endRange<QQmlProfilerService::HandlingSignal>());
- }
-};
-
-struct QQmlCompilingProfiler {
- QQmlCompilingProfiler(const QString &name)
- {
- Q_QML_PROFILE(startCompiling(name));
- }
-
- ~QQmlCompilingProfiler()
- {
- Q_QML_PROFILE(endRange<QQmlProfilerService::Compiling>());
- }
-};
-
-#define Q_QML_VME_PROFILE(Method) Q_QML_PROFILE_IF_ENABLED(Method)
-
-struct QQmlVmeProfiler {
-public:
-
- struct Data {
- Data() : line(0), column(0) {}
- QUrl url;
- int line;
- int column;
- QString typeName;
- };
-
- QQmlVmeProfiler() : running(false) {}
-
- void clear()
- {
- ranges.clear();
- if (running)
- QQmlProfilerService::m_instance->endRange<QQmlProfilerService::Creating>();
- for (int i = 0; i < backgroundRanges.count(); ++i) {
- QQmlProfilerService::m_instance->endRange<QQmlProfilerService::Creating>();
- }
- backgroundRanges.clear();
- running = false;
- }
-
- void startBackground(const QString &typeName)
- {
- if (running) {
- QQmlProfilerService::m_instance->endRange<QQmlProfilerService::Creating>();
- running = false;
- }
- QQmlProfilerService::m_instance->startCreating(typeName);
- backgroundRanges.push(typeName);
- }
-
- void start(const QString &typeName, const QUrl &url, int line, int column)
- {
- switchRange();
- setCurrentRange(typeName, url, line, column);
- QQmlProfilerService::m_instance->startCreating(typeName, url, line, column);
- }
-
- void stop()
- {
- if (running) {
- QQmlProfilerService::m_instance->endRange<QQmlProfilerService::Creating>();
- running = false;
- }
- }
-
- void pop()
- {
- if (ranges.count() > 0) {
- switchRange();
- currentRange = ranges.pop();
- QQmlProfilerService::m_instance->startCreating(currentRange.typeName, currentRange.url,
- currentRange.line, currentRange.column);
- }
- }
-
- void push()
- {
- if (running)
- ranges.push(currentRange);
- }
-
- void foreground(const QUrl &url, int line, int column)
- {
- if (backgroundRanges.count() > 0) {
- switchRange();
- setCurrentRange(backgroundRanges.pop(), url, line, column);
- QQmlProfilerService::m_instance->creatingLocation(url, line, column);
- }
- }
-
-private:
-
- void switchRange()
- {
- if (running)
- QQmlProfilerService::m_instance->endRange<QQmlProfilerService::Creating>();
- else
- running = true;
- }
-
- void setCurrentRange(const QString &typeName, const QUrl &url, int line, int column)
- {
- currentRange.typeName = typeName;
- currentRange.url = url;
- currentRange.line = line;
- currentRange.column = column;
- }
-
- Data currentRange;
- QStack<Data> ranges;
- QStack<QString> backgroundRanges;
- bool running;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 9b83feebb4..11b9353dfe 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -46,7 +46,7 @@
#include "qqmlinfo.h"
#include "qqmlcompiler_p.h"
#include "qqmldata_p.h"
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
#include <private/qqmltrace_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -226,7 +226,8 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
trace.addDetail("Column", columnNo);
if (!updatingFlag()) {
- QQmlBindingProfiler prof(m_url, lineNo, columnNo, QQmlProfilerService::QmlBinding);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
+ QQmlBindingProfiler prof(ep->profiler, m_url, lineNo, columnNo);
setUpdatingFlag(true);
QQmlAbstractExpression::DeleteWatcher watcher(this);
@@ -242,7 +243,6 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a);
} else {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
QV4::Scope scope(ep->v4engine());
ep->referenceScarceResources();
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index d0476a92d4..e5a0df8c32 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -50,7 +50,7 @@
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
#include <private/qv4debugservice_p.h>
#include "qqmlinfo.h"
@@ -356,14 +356,13 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a)
if (QQmlDebugService::isDebuggingEnabled())
QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->m_index).methodSignature()));
- QQmlHandlingSignalProfiler prof(s->m_expression);
-
s->m_isEvaluating = true;
- if (s->m_expression && s->m_expression->engine()) {
+ QQmlEngine *engine;
+ if (s->m_expression && (engine = s->m_expression->engine())) {
+ QQmlHandlingSignalProfiler prof(QQmlEnginePrivate::get(engine)->profiler, s->m_expression);
s->m_expression->evaluate(a);
if (s->m_expression && s->m_expression->hasError()) {
- QQmlEngine *engine = s->m_expression->engine();
QQmlEnginePrivate::warning(engine, s->m_expression->error(engine));
}
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 68d021b5cb..d373c00574 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -556,7 +556,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlUseNewCompiler, QML_NEW_COMPILER)
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0), isDebugging(false),
- outputWarningsToStdErr(true),
+ profiler(0), outputWarningsToStdErr(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0), activeVME(0),
activeObjectCreator(0),
@@ -595,6 +595,12 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
(*iter)->release();
for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
iter.value()->isRegisteredWithEngine = false;
+ delete profiler;
+}
+
+void QQmlEnginePrivate::enableProfiler()
+{
+ profiler = new QQmlProfiler();
}
void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index e292dbf6c0..d5ceea271e 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -102,6 +102,7 @@ class QQmlVME;
class QmlObjectCreator;
class QDir;
class QQmlIncubator;
+class QQmlProfiler;
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
@@ -146,6 +147,8 @@ public:
QQmlContext *rootContext;
bool isDebugging;
bool useNewCompiler;
+ QQmlProfiler *profiler;
+ void enableProfiler();
bool outputWarningsToStdErr;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 7c32d4f19c..1b947c421a 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -49,7 +49,7 @@
#include <private/qqmlthread_p.h>
#include <private/qqmlcompiler_p.h>
#include <private/qqmlcomponent_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qqmlcodegenerator_p.h>
#include <private/qqmltypecompiler_p.h>
@@ -2304,7 +2304,7 @@ void QQmlTypeData::compile()
m_compiledData->url = finalUrl();
m_compiledData->name = finalUrlString();
- QQmlCompilingProfiler prof(m_compiledData->name);
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, m_compiledData->name);
if (m_useNewCompiler) {
QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, parsedQML.data());
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 54c70feecc..fb1dff49fd 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -129,6 +129,7 @@ void QQmlVME::init(QQmlContextData *ctxt, QQmlCompiledData *comp, int start,
rootContext = 0;
engine = ctxt->engine;
+ profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
}
bool QQmlVME::initDeferred(QObject *object)
@@ -168,6 +169,7 @@ bool QQmlVME::initDeferred(QObject *object)
rootContext = 0;
engine = ctxt->engine;
+ profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
return true;
}
@@ -503,7 +505,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.component);
- Q_QML_VME_PROFILE(profiler.startBackground(type.component->name));
+ Q_QML_VME_PROFILE(profiler, startBackground(type.component->name));
states.push(State());
@@ -526,7 +528,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(CreateQMLObject)
QML_BEGIN_INSTR(CompleteQMLObject)
- Q_QML_VME_PROFILE(profiler.foreground(CTXT->url, instr.line, instr.column));
+ Q_QML_VME_PROFILE(profiler, foreground(CTXT->url, instr.line, instr.column));
QObject *o = objects.top();
Q_ASSERT(o);
@@ -570,7 +572,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateCppObject)
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.type);
- Q_QML_VME_PROFILE(profiler.start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
+ Q_QML_VME_PROFILE(profiler, start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
QObject *o = 0;
void *memory = 0;
@@ -643,7 +645,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateSimpleObject)
const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type);
- Q_QML_VME_PROFILE(profiler.start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
+ Q_QML_VME_PROFILE(profiler, start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
::memset(static_cast<void *>(o), 0, instr.typeSize + sizeof(QQmlData));
instr.create(o);
@@ -823,7 +825,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(StoreScriptString)
QML_BEGIN_INSTR(BeginObject)
- Q_QML_VME_PROFILE(profiler.push());
+ Q_QML_VME_PROFILE(profiler, push());
QObject *target = objects.top();
QQmlParserStatus *status = reinterpret_cast<QQmlParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
parserStatus.push(status);
@@ -1087,7 +1089,7 @@ normalExit:
objects.deallocate();
lists.deallocate();
states.clear();
- Q_QML_VME_PROFILE(profiler.stop());
+ Q_QML_VME_PROFILE(profiler, stop());
return rv;
}
@@ -1131,7 +1133,7 @@ void QQmlVME::reset()
// be reported in the second run because we don't clear() here. We accept
// that as the collected data will be incomplete anyway and because not
// calling clear() here is benefitial for the non-profiling case.
- Q_QML_VME_PROFILE(profiler.clear());
+ Q_QML_VME_PROFILE(profiler, clear(true));
}
#ifdef QML_THREADED_VME_INTERPRETER
@@ -1191,7 +1193,7 @@ QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt)
if (componentCompleteEnabled()) { // the qml designer does the component complete later
QQmlTrace trace("VME Component Complete");
while (!parserStatus.isEmpty()) {
- Q_QML_VME_PROFILE(profiler.pop());
+ Q_QML_VME_PROFILE(profiler, pop());
QQmlParserStatus *status = parserStatus.pop();
#ifdef QML_ENABLE_TRACE
QQmlData *data = parserStatusData.pop();
@@ -1211,7 +1213,7 @@ QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt)
return 0;
}
parserStatus.deallocate();
- Q_QML_VME_PROFILE(profiler.clear());
+ Q_QML_VME_PROFILE(profiler, clear());
}
{
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 4da1aec74b..226d498d2c 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -68,7 +68,7 @@
#include <private/qfinitestack_p.h>
#include <private/qqmltrace_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qqmlprofiler_p.h>
QT_BEGIN_NAMESPACE