1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qqmlprofileradapter.h"
#include "qqmlprofilerservice.h"
#include <private/qqmldebugserviceinterfaces_p.h>
QT_BEGIN_NAMESPACE
QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine)
{
engine->profiler = new QQmlProfiler;
init(service, engine->profiler);
}
QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlTypeLoader *loader)
{
QQmlProfiler *profiler = new QQmlProfiler;
loader->setProfiler(profiler);
init(service, profiler);
}
void QQmlProfilerAdapter::init(QQmlProfilerService *service, QQmlProfiler *profiler)
{
next = 0;
setService(service);
connect(this, &QQmlProfilerAdapter::profilingEnabled,
profiler, &QQmlProfiler::startProfiling);
connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
profiler, &QQmlProfiler::startProfiling, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
profiler, &QQmlProfiler::stopProfiling);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
profiler, &QQmlProfiler::stopProfiling, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
profiler, &QQmlProfiler::reportData);
connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
profiler, &QQmlProfiler::setTimer);
connect(profiler, &QQmlProfiler::dataReady,
this, &QQmlProfilerAdapter::receiveData);
}
// convert to QByteArrays that can be sent to the debug client
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
QQmlProfiler::LocationHash &locations,
QList<QByteArray> &messages)
{
QQmlDebugPacket ds;
Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
"You can use at most 31 message types.");
for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0;
++decodedMessageType) {
if (decodedMessageType == QQmlProfilerDefinitions::RangeData
|| (d.messageType & (1 << decodedMessageType)) == 0) {
continue; // RangeData is sent together with RangeLocation
}
if (decodedMessageType == QQmlProfilerDefinitions::RangeEnd
|| decodedMessageType == QQmlProfilerDefinitions::RangeStart) {
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
if (d.locationId != 0)
ds << static_cast<qint64>(d.locationId);
} else {
auto i = locations.find(d.locationId);
if (i != locations.end()) {
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
ds << (i->url.isEmpty() ? i->location.sourceFile : i->url.toString())
<< static_cast<qint32>(i->location.line)
<< static_cast<qint32>(i->location.column);
if (d.messageType & (1 << QQmlProfilerDefinitions::RangeData)) {
// Send both, location and data ...
ds << static_cast<qint64>(d.locationId);
messages.append(ds.squeezedData());
ds.clear();
ds << d.time << int(QQmlProfilerDefinitions::RangeData)
<< static_cast<quint32>(d.detailType)
<< (i->location.sourceFile.isEmpty() ? i->url.toString() :
i->location.sourceFile);
}
ds << static_cast<qint64>(d.locationId);
locations.erase(i); // ... so that we can erase here without missing anything.
} else {
// Skip RangeData and RangeLocation: We've already sent them
continue;
}
}
messages.append(ds.squeezedData());
ds.clear();
}
}
qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
while (next != data.length()) {
const QQmlProfilerData &nextData = data.at(next);
if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
return nextData.time;
qQmlProfilerDataToByteArrays(nextData, locations, messages);
++next;
}
next = 0;
data.clear();
locations.clear();
return -1;
}
void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data,
const QQmlProfiler::LocationHash &new_locations)
{
if (data.isEmpty())
data = new_data;
else
data.append(new_data);
if (locations.isEmpty())
locations = new_locations;
else
locations.insert(new_locations);
service->dataReady(this);
}
QT_END_NAMESPACE
#include "moc_qqmlprofileradapter.cpp"
|