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.h223
1 files changed, 151 insertions, 72 deletions
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 24001159f3..1380599fb7 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -54,6 +54,8 @@
#include <private/qv4function_p.h>
#include <private/qqmlboundsignal_p.h>
#include <private/qfinitestack_p.h>
+#include <private/qqmlbinding_p.h>
+#include <private/qqmlcompiler_p.h>
#include "qqmlprofilerdefinitions_p.h"
#include "qqmlabstractprofileradapter_p.h"
@@ -77,40 +79,18 @@ QT_BEGIN_NAMESPACE
// 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.
-struct Q_AUTOTEST_EXPORT QQmlProfilerData
+struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions
{
- 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) {}
-
+ QQmlProfilerData(qint64 time = -1, int messageType = -1,
+ RangeType detailType = MaximumRangeType, quintptr locationId = 0) :
+ time(time), locationId(locationId), messageType(messageType), detailType(detailType)
+ {}
qint64 time;
- int messageType; //bit field of QQmlProfilerService::Message
- int detailType;
+ quintptr locationId;
- // RangeData prefers detailString; RangeLocation prefers detailUrl.
- QString detailString; //used by RangeData and possibly by RangeLocation
- QUrl detailUrl; //used by RangeLocation and possibly by RangeData
-
- int x; //used by RangeLocation
- int y; //used by RangeLocation
+ int messageType; //bit field of QQmlProfilerService::Message
+ RangeType detailType;
};
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
@@ -118,58 +98,166 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
public:
- void startBinding(const QQmlSourceLocation &location)
+
+ class BindingRefCount : public QQmlRefCount {
+ public:
+ BindingRefCount(QQmlBinding *binding):
+ m_binding(binding)
+ {
+ m_binding->ref.ref();
+ }
+
+ BindingRefCount(const BindingRefCount &other) :
+ QQmlRefCount(other), m_binding(other.m_binding)
+ {
+ m_binding->ref.ref();
+ }
+
+ BindingRefCount &operator=(const BindingRefCount &other)
+ {
+ if (this != &other) {
+ QQmlRefCount::operator=(other);
+ other.m_binding->ref.ref();
+ if (!m_binding->ref.deref())
+ delete m_binding;
+ m_binding = other.m_binding;
+ }
+ return *this;
+ }
+
+ ~BindingRefCount()
+ {
+ if (!m_binding->ref.deref())
+ delete m_binding;
+ }
+
+ private:
+ QQmlBinding *m_binding;
+ };
+
+ struct Location {
+ Location(const QQmlSourceLocation &location = QQmlSourceLocation(),
+ const QUrl &url = QUrl()) :
+ location(location), url(url) {}
+ QQmlSourceLocation location;
+ QUrl url;
+ };
+
+ // Unfortunately we have to resolve the locations right away because the QML context might not
+ // be available anymore when we send the data.
+ struct RefLocation : public Location {
+ RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr)
+ {}
+
+ RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
+ Location(function->sourceLocation()), locationType(Binding),
+ ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt)
+ {}
+
+ RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
+ const QString &type) :
+ Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
+ locationType(Creating), ref(ref)
+ {}
+
+ RefLocation(QQmlBoundSignalExpression *ref) :
+ Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref)
+ {}
+
+ RefLocation(QQmlDataBlob *ref) :
+ Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref)
+ {}
+
+ bool isValid() const
+ {
+ return locationType != MaximumRangeType;
+ }
+
+ RangeType locationType;
+ QQmlRefPointer<QQmlRefCount> ref;
+ };
+
+ typedef QHash<quintptr, Location> LocationHash;
+
+ void startBinding(QQmlBinding *binding, QV4::FunctionObject *function)
{
+ quintptr locationId(id(binding));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
- (1 << RangeStart | 1 << RangeLocation), 1 << Binding,
- location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column)));
+ (1 << RangeStart | 1 << RangeLocation), Binding,
+ locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(binding, function);
}
// Have toByteArrays() construct another RangeData event from the same QString later.
// This is somewhat pointless but important for backwards compatibility.
- void startCompiling(const QUrl &url)
+ void startCompiling(QQmlDataBlob *blob)
{
+ quintptr locationId(id(blob));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
- 1 << Compiling, url, 1, 1));
+ Compiling, locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(blob);
}
- void startHandlingSignal(const QQmlSourceLocation &location)
+ void startHandlingSignal(QQmlBoundSignalExpression *expression)
{
+ quintptr locationId(id(expression));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
- (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal,
- location.sourceFile, location.line, location.column));
+ (1 << RangeStart | 1 << RangeLocation), HandlingSignal,
+ locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(expression);
}
void startCreating()
{
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, 1 << Creating));
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating));
}
- void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
+ void startCreating(const QV4::CompiledData::Object *obj)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
- 1 << Creating, typeName, fileName, line, column));
+ Creating, id(obj)));
}
- void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column)
+ void updateCreating(const QV4::CompiledData::Object *obj, QQmlCompiledData *ref,
+ const QUrl &url, const QString &type)
{
+ quintptr locationId(id(obj));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeLocation | 1 << RangeData),
- 1 << Creating, typeName, fileName, line, column));
+ Creating, locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(ref, url, obj, type);
}
template<RangeType Range>
void endRange()
{
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range));
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, Range));
}
QQmlProfiler();
quint64 featuresEnabled;
+ template<typename Object>
+ static quintptr id(const Object *pointer)
+ {
+ return reinterpret_cast<quintptr>(pointer);
+ }
+
public slots:
void startProfiling(quint64 features);
void stopProfiling();
@@ -177,10 +265,11 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QVector<QQmlProfilerData> &);
+ void dataReady(const QVector<QQmlProfilerData> &, const QQmlProfiler::LocationHash &);
protected:
QElapsedTimer m_timer;
+ QHash<quintptr, RefLocation> m_locations;
QVector<QQmlProfilerData> m_data;
};
@@ -194,11 +283,12 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
};
struct QQmlBindingProfiler : public QQmlProfilerHelper {
- QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) :
+ QQmlBindingProfiler(QQmlProfiler *profiler, QQmlBinding *binding,
+ QV4::FunctionObject *function) :
QQmlProfilerHelper(profiler)
{
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
- startBinding(function->sourceLocation()));
+ startBinding(binding, function));
}
~QQmlBindingProfiler()
@@ -213,7 +303,7 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
QQmlProfilerHelper(profiler)
{
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
- startHandlingSignal(expression->sourceLocation()));
+ startHandlingSignal(expression));
}
~QQmlHandlingSignalProfiler()
@@ -224,10 +314,10 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
};
struct QQmlCompilingProfiler : public QQmlProfilerHelper {
- QQmlCompilingProfiler(QQmlProfiler *profiler, const QUrl &url) :
+ QQmlCompilingProfiler(QQmlProfiler *profiler, QQmlDataBlob *blob) :
QQmlProfilerHelper(profiler)
{
- Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(url));
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(blob));
}
~QQmlCompilingProfiler()
@@ -239,14 +329,6 @@ struct QQmlCompilingProfiler : public QQmlProfilerHelper {
struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
public:
- struct Data {
- Data() : m_line(0), m_column(0) {}
- QUrl m_url;
- int m_line;
- int m_column;
- QString m_typeName;
- };
-
QQmlVmeProfiler() : profiler(0) {}
void init(QQmlProfiler *p, int maxDepth)
@@ -255,30 +337,30 @@ public:
ranges.allocate(maxDepth);
}
- Data pop()
+ const QV4::CompiledData::Object *pop()
{
if (ranges.count() > 0)
return ranges.pop();
else
- return Data();
+ return nullptr;
}
- void push(const Data &data)
+ void push(const QV4::CompiledData::Object *object)
{
if (ranges.capacity() > ranges.count())
- ranges.push(data);
+ ranges.push(object);
}
QQmlProfiler *profiler;
private:
- QFiniteStack<Data> ranges;
+ QFiniteStack<const QV4::CompiledData::Object *> ranges;
};
#define Q_QML_OC_PROFILE(member, Code)\
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
-class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data {
+class QQmlObjectCreationProfiler {
public:
QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
@@ -291,13 +373,10 @@ public:
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>());
}
- void update(const QString &typeName, const QUrl &url, int line, int column)
+ void update(QQmlCompiledData *ref, const QV4::CompiledData::Object *obj,
+ const QString &typeName, const QUrl &url)
{
- profiler->updateCreating(typeName, url, line, column);
- m_typeName = typeName;
- m_url = url;
- m_line = line;
- m_column = column;
+ profiler->updateCreating(obj, ref, url, typeName);
}
private:
@@ -310,8 +389,7 @@ public:
profiler(parent->profiler)
{
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, {
- QQmlVmeProfiler::Data data = parent->pop();
- profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column);
+ profiler->startCreating(parent->pop());
});
}
@@ -326,5 +404,6 @@ private:
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
+Q_DECLARE_METATYPE(QQmlProfiler::LocationHash)
#endif // QQMLPROFILER_P_H