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

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp