2014-01-24 11:44:49 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2014-01-24 11:44:49 +00:00
|
|
|
**
|
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2014-01-24 11:44:49 +00:00
|
|
|
** 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
|
2015-01-28 11:55:39 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-19 09:38:36 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2014-01-24 11:44:49 +00:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2016-01-19 09:38:36 +00:00
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
2014-01-24 11:44:49 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
2014-01-24 11:44:49 +00:00
|
|
|
**
|
|
|
|
** $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>
|
2014-04-02 10:02:14 +00:00
|
|
|
#include <private/qfinitestack_p.h>
|
2014-01-24 11:44:49 +00:00
|
|
|
#include "qqmlprofilerdefinitions_p.h"
|
|
|
|
#include "qqmlabstractprofileradapter_p.h"
|
|
|
|
|
|
|
|
#include <QUrl>
|
|
|
|
#include <QString>
|
|
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2014-09-03 17:28:35 +00:00
|
|
|
#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)\
|
|
|
|
if (profiler && (profiler->featuresEnabled & (1 << feature))) {\
|
2014-01-24 11:44:49 +00:00
|
|
|
Code;\
|
|
|
|
} else\
|
|
|
|
(void)0
|
|
|
|
|
2014-09-03 17:28:35 +00:00
|
|
|
#define Q_QML_PROFILE(feature, profiler, Method)\
|
|
|
|
Q_QML_PROFILE_IF_ENABLED(feature, profiler, profiler->Method)
|
2014-01-24 11:44:49 +00:00
|
|
|
|
|
|
|
// 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
|
2015-07-20 16:09:42 +00:00
|
|
|
// independently when converting to QByteArrays. Thus you can only pack
|
|
|
|
// messages if their data doesn't overlap. It's up to you to figure that
|
|
|
|
// out.
|
2014-01-24 11:44:49 +00:00
|
|
|
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;
|
|
|
|
|
2015-08-11 10:47:28 +00:00
|
|
|
// RangeData prefers detailString; RangeLocation prefers detailUrl.
|
2014-01-24 11:44:49 +00:00
|
|
|
QString detailString; //used by RangeData and possibly by RangeLocation
|
2015-08-11 10:47:28 +00:00
|
|
|
QUrl detailUrl; //used by RangeLocation and possibly by RangeData
|
2014-01-24 11:44:49 +00:00
|
|
|
|
|
|
|
int x; //used by RangeLocation
|
|
|
|
int y; //used by RangeLocation
|
|
|
|
};
|
|
|
|
|
|
|
|
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
|
|
|
|
|
|
|
|
class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2015-04-10 10:34:36 +00:00
|
|
|
void startBinding(const QQmlSourceLocation &location)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
|
|
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
|
|
|
(1 << RangeStart | 1 << RangeLocation), 1 << Binding,
|
2015-04-10 10:34:36 +00:00
|
|
|
location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column)));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Have toByteArrays() construct another RangeData event from the same QString later.
|
|
|
|
// This is somewhat pointless but important for backwards compatibility.
|
2015-08-11 10:47:28 +00:00
|
|
|
void startCompiling(const QUrl &url)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
|
|
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
|
|
|
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
|
2015-08-11 10:47:28 +00:00
|
|
|
1 << Compiling, url, 1, 1));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-03-04 08:45:13 +00:00
|
|
|
void startHandlingSignal(const QQmlSourceLocation &location)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
|
|
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
|
|
|
(1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal,
|
2014-03-04 08:45:13 +00:00
|
|
|
location.sourceFile, location.line, location.column));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
void startCreating()
|
|
|
|
{
|
|
|
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, 1 << Creating));
|
|
|
|
}
|
|
|
|
|
2014-01-24 11:44:49 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-04-02 10:02:14 +00:00
|
|
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
|
|
|
(1 << RangeLocation | 1 << RangeData),
|
|
|
|
1 << Creating, typeName, fileName, line, column));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<RangeType Range>
|
|
|
|
void endRange()
|
|
|
|
{
|
|
|
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range));
|
|
|
|
}
|
|
|
|
|
|
|
|
QQmlProfiler();
|
|
|
|
|
2014-09-03 17:28:35 +00:00
|
|
|
quint64 featuresEnabled;
|
2014-01-24 11:44:49 +00:00
|
|
|
|
|
|
|
public slots:
|
2014-09-03 17:28:35 +00:00
|
|
|
void startProfiling(quint64 features);
|
2014-01-24 11:44:49 +00:00
|
|
|
void stopProfiling();
|
|
|
|
void reportData();
|
|
|
|
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
|
|
|
|
|
|
|
signals:
|
2015-07-20 16:15:05 +00:00
|
|
|
void dataReady(const QVector<QQmlProfilerData> &);
|
2014-01-24 11:44:49 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
QElapsedTimer m_timer;
|
2015-07-28 11:22:33 +00:00
|
|
|
QVector<QQmlProfilerData> m_data;
|
2014-01-24 11:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// RAII helper structs
|
|
|
|
//
|
|
|
|
|
|
|
|
struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
|
|
|
|
QQmlProfiler *profiler;
|
|
|
|
QQmlProfilerHelper(QQmlProfiler *profiler) : profiler(profiler) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct QQmlBindingProfiler : public QQmlProfilerHelper {
|
2015-04-10 10:34:36 +00:00
|
|
|
QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) :
|
2014-01-24 11:44:49 +00:00
|
|
|
QQmlProfilerHelper(profiler)
|
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
|
2015-04-10 10:34:36 +00:00
|
|
|
startBinding(function->sourceLocation()));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~QQmlBindingProfiler()
|
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
|
|
|
|
endRange<Binding>());
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
|
|
|
|
QQmlHandlingSignalProfiler(QQmlProfiler *profiler, QQmlBoundSignalExpression *expression) :
|
|
|
|
QQmlProfilerHelper(profiler)
|
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
|
|
|
|
startHandlingSignal(expression->sourceLocation()));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~QQmlHandlingSignalProfiler()
|
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
|
|
|
|
endRange<QQmlProfiler::HandlingSignal>());
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct QQmlCompilingProfiler : public QQmlProfilerHelper {
|
2015-08-11 10:47:28 +00:00
|
|
|
QQmlCompilingProfiler(QQmlProfiler *profiler, const QUrl &url) :
|
2014-01-24 11:44:49 +00:00
|
|
|
QQmlProfilerHelper(profiler)
|
|
|
|
{
|
2015-08-11 10:47:28 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(url));
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~QQmlCompilingProfiler()
|
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, endRange<Compiling>());
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
|
|
|
|
public:
|
|
|
|
|
|
|
|
struct Data {
|
2014-04-02 10:02:14 +00:00
|
|
|
Data() : m_line(0), m_column(0) {}
|
|
|
|
QUrl m_url;
|
|
|
|
int m_line;
|
|
|
|
int m_column;
|
|
|
|
QString m_typeName;
|
2014-01-24 11:44:49 +00:00
|
|
|
};
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
QQmlVmeProfiler() : profiler(0) {}
|
2014-01-24 11:44:49 +00:00
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
void init(QQmlProfiler *p, int maxDepth)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-04-02 10:02:14 +00:00
|
|
|
profiler = p;
|
|
|
|
ranges.allocate(maxDepth);
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
Data pop()
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-04-02 10:02:14 +00:00
|
|
|
if (ranges.count() > 0)
|
|
|
|
return ranges.pop();
|
|
|
|
else
|
|
|
|
return Data();
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
void push(const Data &data)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-04-02 10:02:14 +00:00
|
|
|
if (ranges.capacity() > ranges.count())
|
|
|
|
ranges.push(data);
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
QQmlProfiler *profiler;
|
2014-01-24 11:44:49 +00:00
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
private:
|
|
|
|
QFiniteStack<Data> ranges;
|
|
|
|
};
|
|
|
|
|
2014-09-03 17:28:35 +00:00
|
|
|
#define Q_QML_OC_PROFILE(member, Code)\
|
|
|
|
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
|
2014-04-02 10:02:14 +00:00
|
|
|
|
|
|
|
class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data {
|
|
|
|
public:
|
|
|
|
|
|
|
|
QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating());
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
~QQmlObjectCreationProfiler()
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>());
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
void update(const QString &typeName, const QUrl &url, int line, int column)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-04-02 10:02:14 +00:00
|
|
|
profiler->updateCreating(typeName, url, line, column);
|
|
|
|
m_typeName = typeName;
|
|
|
|
m_url = url;
|
|
|
|
m_line = line;
|
|
|
|
m_column = column;
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-04-02 10:02:14 +00:00
|
|
|
QQmlProfiler *profiler;
|
|
|
|
};
|
2014-01-24 11:44:49 +00:00
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
class QQmlObjectCompletionProfiler {
|
|
|
|
public:
|
|
|
|
QQmlObjectCompletionProfiler(QQmlVmeProfiler *parent) :
|
|
|
|
profiler(parent->profiler)
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, {
|
2014-04-02 10:02:14 +00:00
|
|
|
QQmlVmeProfiler::Data data = parent->pop();
|
|
|
|
profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column);
|
|
|
|
});
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2014-04-02 10:02:14 +00:00
|
|
|
~QQmlObjectCompletionProfiler()
|
2014-01-24 11:44:49 +00:00
|
|
|
{
|
2014-09-03 17:28:35 +00:00
|
|
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler,
|
|
|
|
endRange<QQmlProfilerDefinitions::Creating>());
|
2014-01-24 11:44:49 +00:00
|
|
|
}
|
2014-04-02 10:02:14 +00:00
|
|
|
private:
|
|
|
|
QQmlProfiler *profiler;
|
2014-01-24 11:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
QT_END_NAMESPACE
|
2015-07-20 16:15:05 +00:00
|
|
|
Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
|
2014-01-24 11:44:49 +00:00
|
|
|
|
|
|
|
#endif // QQMLPROFILER_P_H
|