Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4profileradapter.cpp
Go to the documentation of this file.
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// Qt-Security score:significant
4
7
9
10QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) :
11 m_functionCallPos(0), m_memoryPos(0)
12{
13 setService(service);
14 engine->setProfiler(new QV4::Profiling::Profiler(engine));
15 connect(this, &QQmlAbstractProfilerAdapter::profilingEnabled,
16 this, &QV4ProfilerAdapter::forwardEnabled);
17 connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
18 this, &QV4ProfilerAdapter::forwardEnabledWhileWaiting, Qt::DirectConnection);
19 connect(this, &QV4ProfilerAdapter::v4ProfilingEnabled,
20 engine->profiler(), &QV4::Profiling::Profiler::startProfiling);
21 connect(this, &QV4ProfilerAdapter::v4ProfilingEnabledWhileWaiting,
22 engine->profiler(), &QV4::Profiling::Profiler::startProfiling, Qt::DirectConnection);
23 connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
24 engine->profiler(), &QV4::Profiling::Profiler::stopProfiling);
25 connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
26 engine->profiler(), &QV4::Profiling::Profiler::stopProfiling,
27 Qt::DirectConnection);
28 connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
29 engine->profiler(), &QV4::Profiling::Profiler::reportData);
30 connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
31 engine->profiler(), &QV4::Profiling::Profiler::setTimer);
32 connect(engine->profiler(), &QV4::Profiling::Profiler::dataReady,
33 this, &QV4ProfilerAdapter::receiveData);
34}
35
36qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages,
37 QQmlDebugPacket &d)
38{
39 // Make it const, so that we cannot accidentally detach it.
40 const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData = m_memoryData;
41
42 while (memoryData.size() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) {
43 const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos];
44 d << props.timestamp << int(MemoryAllocation) << int(props.type) << props.size;
45 ++m_memoryPos;
46 messages.append(d.squeezedData());
47 d.clear();
48 }
49 return memoryData.size() == m_memoryPos ? -1 : memoryData[m_memoryPos].timestamp;
50}
51
52qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
53 qint64 callNext, QQmlDebugPacket &d)
54{
55 qint64 memoryNext = -1;
56
57 if (callNext == -1) {
58 m_functionLocations.clear();
59 m_functionCallData.clear();
60 m_functionCallPos = 0;
61 memoryNext = appendMemoryEvents(until, messages, d);
62 } else {
63 memoryNext = appendMemoryEvents(qMin(callNext, until), messages, d);
64 }
65
66 if (memoryNext == -1) {
67 m_memoryData.clear();
68 m_memoryPos = 0;
69 return callNext;
70 }
71
72 return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
73}
74
75qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
76{
77 QQmlDebugPacket d;
78
79 // Make it const, so that we cannot accidentally detach it.
80 const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData;
81
82 while (true) {
83 while (!m_stack.isEmpty() &&
84 (m_functionCallPos == functionCallData.size() ||
85 m_stack.top() <= functionCallData[m_functionCallPos].start)) {
86 if (m_stack.top() > until || messages.size() > s_numMessagesPerBatch)
87 return finalizeMessages(until, messages, m_stack.top(), d);
88
89 appendMemoryEvents(m_stack.top(), messages, d);
90 d << m_stack.pop() << int(RangeEnd) << int(Javascript);
91 messages.append(d.squeezedData());
92 d.clear();
93 }
94 while (m_functionCallPos != functionCallData.size() &&
95 (m_stack.empty() || functionCallData[m_functionCallPos].start < m_stack.top())) {
96 const QV4::Profiling::FunctionCallProperties &props =
97 functionCallData[m_functionCallPos];
98 if (props.start > until || messages.size() > s_numMessagesPerBatch)
99 return finalizeMessages(until, messages, props.start, d);
100
101 appendMemoryEvents(props.start, messages, d);
102 auto location = m_functionLocations.constFind(props.id);
103
104 d << props.start << int(RangeStart) << int(Javascript) << static_cast<qint64>(props.id);
105 if (location != m_functionLocations.cend()) {
106 messages.push_back(d.squeezedData());
107 d.clear();
108 d << props.start << int(RangeLocation) << int(Javascript) << location->file << location->line
109 << location->column << static_cast<qint64>(props.id);
110 messages.push_back(d.squeezedData());
111 d.clear();
112 d << props.start << int(RangeData) << int(Javascript) << location->name
113 << static_cast<qint64>(props.id);
114 m_functionLocations.erase(location);
115 }
116 messages.push_back(d.squeezedData());
117 d.clear();
118 m_stack.push(props.end);
119 ++m_functionCallPos;
120 }
121 if (m_stack.empty() && m_functionCallPos == functionCallData.size())
122 return finalizeMessages(until, messages, -1, d);
123 }
124}
125
127 const QV4::Profiling::FunctionLocationHash &locations,
128 const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData,
129 const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData)
130{
131 // In rare cases it could be that another flush or stop event is processed while data from
132 // the previous one is still pending. In that case we just append the data.
133 if (m_functionLocations.isEmpty())
134 m_functionLocations = locations;
135 else
136 m_functionLocations.insert(locations);
137
138 if (m_functionCallData.isEmpty())
139 m_functionCallData = functionCallData;
140 else
141 m_functionCallData.append(functionCallData);
142
143 if (m_memoryData.isEmpty())
144 m_memoryData = memoryData;
145 else
146 m_memoryData.append(memoryData);
147
148 service->dataReady(this);
149}
150
151quint64 QV4ProfilerAdapter::translateFeatures(quint64 qmlFeatures)
152{
153 quint64 v4Features = 0;
154 const quint64 one = 1;
155 if (qmlFeatures & (one << ProfileJavaScript))
156 v4Features |= (one << QV4::Profiling::FeatureFunctionCall);
157 if (qmlFeatures & (one << ProfileMemory))
158 v4Features |= (one << QV4::Profiling::FeatureMemoryAllocation);
159 return v4Features;
160}
161
162void QV4ProfilerAdapter::forwardEnabled(quint64 features)
163{
164 emit v4ProfilingEnabled(translateFeatures(features));
165}
166
167void QV4ProfilerAdapter::forwardEnabledWhileWaiting(quint64 features)
168{
169 emit v4ProfilingEnabledWhileWaiting(translateFeatures(features));
170}
171
172QT_END_NAMESPACE
173
174#include "moc_qv4profileradapter.cpp"
void receiveData(const QV4::Profiling::FunctionLocationHash &, const QVector< QV4::Profiling::FunctionCallProperties > &, const QVector< QV4::Profiling::MemoryAllocationProperties > &)
virtual qint64 sendMessages(qint64 until, QList< QByteArray > &messages) override
Combined button and popup list for selecting options.