aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/debugger/qqmlprofiler_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/debugger/qqmlprofiler_p.h')
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h368
1 files changed, 368 insertions, 0 deletions
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