aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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