Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp

Issue 2295913003: [DevTools] Switch from platform/v8_inspector to v8/v8-inspector.h. (Closed)
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/v8_inspector/V8ProfilerAgentImpl.h"
6
7 #include "platform/v8_inspector/Atomics.h"
8 #include "platform/v8_inspector/StringUtil.h"
9 #include "platform/v8_inspector/V8Debugger.h"
10 #include "platform/v8_inspector/V8InspectorImpl.h"
11 #include "platform/v8_inspector/V8InspectorSessionImpl.h"
12 #include "platform/v8_inspector/V8StackTraceImpl.h"
13 #include "platform/v8_inspector/protocol/Protocol.h"
14 #include <v8-profiler.h>
15
16 #include <vector>
17
18 #define ENSURE_V8_VERSION(major, minor) \
19 (V8_MAJOR_VERSION * 1000 + V8_MINOR_VERSION >= (major) * 1000 + (minor))
20
21 namespace v8_inspector {
22
23 namespace ProfilerAgentState {
24 static const char samplingInterval[] = "samplingInterval";
25 static const char userInitiatedProfiling[] = "userInitiatedProfiling";
26 static const char profilerEnabled[] = "profilerEnabled";
27 }
28
29 namespace {
30
31 std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>> buildInsp ectorObjectForPositionTicks(const v8::CpuProfileNode* node)
32 {
33 unsigned lineCount = node->GetHitLineCount();
34 if (!lineCount)
35 return nullptr;
36 auto array = protocol::Array<protocol::Profiler::PositionTickInfo>::create() ;
37 std::vector<v8::CpuProfileNode::LineTick> entries(lineCount);
38 if (node->GetLineTicks(&entries[0], lineCount)) {
39 for (unsigned i = 0; i < lineCount; i++) {
40 std::unique_ptr<protocol::Profiler::PositionTickInfo> line = protoco l::Profiler::PositionTickInfo::create()
41 .setLine(entries[i].line)
42 .setTicks(entries[i].hit_count).build();
43 array->addItem(std::move(line));
44 }
45 }
46 return array;
47 }
48
49 std::unique_ptr<protocol::Profiler::ProfileNode> buildInspectorObjectFor(v8::Iso late* isolate, const v8::CpuProfileNode* node)
50 {
51 v8::HandleScope handleScope(isolate);
52 auto callFrame = protocol::Runtime::CallFrame::create()
53 .setFunctionName(toProtocolString(node->GetFunctionName()))
54 .setScriptId(String16::fromInteger(node->GetScriptId()))
55 .setUrl(toProtocolString(node->GetScriptResourceName()))
56 .setLineNumber(node->GetLineNumber() - 1)
57 .setColumnNumber(node->GetColumnNumber() - 1)
58 .build();
59 auto result = protocol::Profiler::ProfileNode::create()
60 .setCallFrame(std::move(callFrame))
61 .setHitCount(node->GetHitCount())
62 .setId(node->GetNodeId()).build();
63
64 const int childrenCount = node->GetChildrenCount();
65 if (childrenCount) {
66 auto children = protocol::Array<int>::create();
67 for (int i = 0; i < childrenCount; i++)
68 children->addItem(node->GetChild(i)->GetNodeId());
69 result->setChildren(std::move(children));
70 }
71
72 const char* deoptReason = node->GetBailoutReason();
73 if (deoptReason && deoptReason[0] && strcmp(deoptReason, "no reason"))
74 result->setDeoptReason(deoptReason);
75
76 auto positionTicks = buildInspectorObjectForPositionTicks(node);
77 if (positionTicks)
78 result->setPositionTicks(std::move(positionTicks));
79
80 return result;
81 }
82
83 std::unique_ptr<protocol::Array<int>> buildInspectorObjectForSamples(v8::CpuProf ile* v8profile)
84 {
85 auto array = protocol::Array<int>::create();
86 int count = v8profile->GetSamplesCount();
87 for (int i = 0; i < count; i++)
88 array->addItem(v8profile->GetSample(i)->GetNodeId());
89 return array;
90 }
91
92 std::unique_ptr<protocol::Array<int>> buildInspectorObjectForTimestamps(v8::CpuP rofile* v8profile)
93 {
94 auto array = protocol::Array<int>::create();
95 int count = v8profile->GetSamplesCount();
96 uint64_t lastTime = v8profile->GetStartTime();
97 for (int i = 0; i < count; i++) {
98 uint64_t ts = v8profile->GetSampleTimestamp(i);
99 array->addItem(static_cast<int>(ts - lastTime));
100 lastTime = ts;
101 }
102 return array;
103 }
104
105 void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node, prot ocol::Array<protocol::Profiler::ProfileNode>* list)
106 {
107 list->addItem(buildInspectorObjectFor(isolate, node));
108 const int childrenCount = node->GetChildrenCount();
109 for (int i = 0; i < childrenCount; i++)
110 flattenNodesTree(isolate, node->GetChild(i), list);
111 }
112
113 std::unique_ptr<protocol::Profiler::Profile> createCPUProfile(v8::Isolate* isola te, v8::CpuProfile* v8profile)
114 {
115 auto nodes = protocol::Array<protocol::Profiler::ProfileNode>::create();
116 flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get());
117 return protocol::Profiler::Profile::create()
118 .setNodes(std::move(nodes))
119 .setStartTime(static_cast<double>(v8profile->GetStartTime()))
120 .setEndTime(static_cast<double>(v8profile->GetEndTime()))
121 .setSamples(buildInspectorObjectForSamples(v8profile))
122 .setTimeDeltas(buildInspectorObjectForTimestamps(v8profile)).build();
123 }
124
125 std::unique_ptr<protocol::Debugger::Location> currentDebugLocation(V8InspectorIm pl* inspector)
126 {
127 std::unique_ptr<V8StackTraceImpl> callStack = inspector->debugger()->capture StackTrace(false /* fullStack */);
128 auto location = protocol::Debugger::Location::create()
129 .setScriptId(toString16(callStack->topScriptId()))
130 .setLineNumber(callStack->topLineNumber()).build();
131 location->setColumnNumber(callStack->topColumnNumber());
132 return location;
133 }
134
135 volatile int s_lastProfileId = 0;
136
137 } // namespace
138
139 class V8ProfilerAgentImpl::ProfileDescriptor {
140 public:
141 ProfileDescriptor(const String16& id, const String16& title)
142 : m_id(id)
143 , m_title(title) { }
144 String16 m_id;
145 String16 m_title;
146 };
147
148 V8ProfilerAgentImpl::V8ProfilerAgentImpl(V8InspectorSessionImpl* session, protoc ol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state)
149 : m_session(session)
150 , m_isolate(m_session->inspector()->isolate())
151 , m_profiler(nullptr)
152 , m_state(state)
153 , m_frontend(frontendChannel)
154 , m_enabled(false)
155 , m_recordingCPUProfile(false)
156 {
157 }
158
159 V8ProfilerAgentImpl::~V8ProfilerAgentImpl()
160 {
161 #if ENSURE_V8_VERSION(5, 4)
162 if (m_profiler)
163 m_profiler->Dispose();
164 #endif
165 }
166
167 void V8ProfilerAgentImpl::consoleProfile(const String16& title)
168 {
169 if (!m_enabled)
170 return;
171 String16 id = nextProfileId();
172 m_startedProfiles.push_back(ProfileDescriptor(id, title));
173 startProfiling(id);
174 m_frontend.consoleProfileStarted(id, currentDebugLocation(m_session->inspect or()), title);
175 }
176
177 void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title)
178 {
179 if (!m_enabled)
180 return;
181 String16 id;
182 String16 resolvedTitle;
183 // Take last started profile if no title was passed.
184 if (title.isEmpty()) {
185 if (m_startedProfiles.empty())
186 return;
187 id = m_startedProfiles.back().m_id;
188 resolvedTitle = m_startedProfiles.back().m_title;
189 m_startedProfiles.pop_back();
190 } else {
191 for (size_t i = 0; i < m_startedProfiles.size(); i++) {
192 if (m_startedProfiles[i].m_title == title) {
193 resolvedTitle = title;
194 id = m_startedProfiles[i].m_id;
195 m_startedProfiles.erase(m_startedProfiles.begin() + i);
196 break;
197 }
198 }
199 if (id.isEmpty())
200 return;
201 }
202 std::unique_ptr<protocol::Profiler::Profile> profile = stopProfiling(id, tru e);
203 if (!profile)
204 return;
205 std::unique_ptr<protocol::Debugger::Location> location = currentDebugLocatio n(m_session->inspector());
206 m_frontend.consoleProfileFinished(id, std::move(location), std::move(profile ), resolvedTitle);
207 }
208
209 void V8ProfilerAgentImpl::enable(ErrorString*)
210 {
211 if (m_enabled)
212 return;
213 m_enabled = true;
214 #if ENSURE_V8_VERSION(5, 4)
215 DCHECK(!m_profiler);
216 m_profiler = v8::CpuProfiler::New(m_isolate);
217 #endif
218 m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
219 }
220
221 void V8ProfilerAgentImpl::disable(ErrorString* errorString)
222 {
223 if (!m_enabled)
224 return;
225 for (size_t i = m_startedProfiles.size(); i > 0; --i)
226 stopProfiling(m_startedProfiles[i - 1].m_id, false);
227 m_startedProfiles.clear();
228 stop(nullptr, nullptr);
229 #if ENSURE_V8_VERSION(5, 4)
230 m_profiler->Dispose();
231 m_profiler = nullptr;
232 #endif
233 m_enabled = false;
234 m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
235 }
236
237 void V8ProfilerAgentImpl::setSamplingInterval(ErrorString* error, int interval)
238 {
239 if (m_recordingCPUProfile) {
240 *error = "Cannot change sampling interval when profiling.";
241 return;
242 }
243 m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
244 profiler()->SetSamplingInterval(interval);
245 }
246
247 void V8ProfilerAgentImpl::restore()
248 {
249 DCHECK(!m_enabled);
250 if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false))
251 return;
252 m_enabled = true;
253 #if ENSURE_V8_VERSION(5, 4)
254 DCHECK(!m_profiler);
255 m_profiler = v8::CpuProfiler::New(m_isolate);
256 #endif
257 int interval = 0;
258 m_state->getInteger(ProfilerAgentState::samplingInterval, &interval);
259 if (interval)
260 profiler()->SetSamplingInterval(interval);
261 if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, fal se)) {
262 ErrorString error;
263 start(&error);
264 }
265 }
266
267 void V8ProfilerAgentImpl::start(ErrorString* error)
268 {
269 if (m_recordingCPUProfile)
270 return;
271 if (!m_enabled) {
272 *error = "Profiler is not enabled";
273 return;
274 }
275 m_recordingCPUProfile = true;
276 m_frontendInitiatedProfileId = nextProfileId();
277 startProfiling(m_frontendInitiatedProfileId);
278 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
279 }
280
281 void V8ProfilerAgentImpl::stop(ErrorString* errorString, std::unique_ptr<protoco l::Profiler::Profile>* profile)
282 {
283 if (!m_recordingCPUProfile) {
284 if (errorString)
285 *errorString = "No recording profiles found";
286 return;
287 }
288 m_recordingCPUProfile = false;
289 std::unique_ptr<protocol::Profiler::Profile> cpuProfile = stopProfiling(m_fr ontendInitiatedProfileId, !!profile);
290 if (profile) {
291 *profile = std::move(cpuProfile);
292 if (!profile->get() && errorString)
293 *errorString = "Profile is not found";
294 }
295 m_frontendInitiatedProfileId = String16();
296 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
297 }
298
299 String16 V8ProfilerAgentImpl::nextProfileId()
300 {
301 return String16::fromInteger(atomicIncrement(&s_lastProfileId));
302 }
303
304 void V8ProfilerAgentImpl::startProfiling(const String16& title)
305 {
306 v8::HandleScope handleScope(m_isolate);
307 profiler()->StartProfiling(toV8String(m_isolate, title), true);
308 }
309
310 std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling( const String16& title, bool serialize)
311 {
312 v8::HandleScope handleScope(m_isolate);
313 v8::CpuProfile* profile = profiler()->StopProfiling(toV8String(m_isolate, ti tle));
314 if (!profile)
315 return nullptr;
316 std::unique_ptr<protocol::Profiler::Profile> result;
317 if (serialize)
318 result = createCPUProfile(m_isolate, profile);
319 profile->Delete();
320 return result;
321 }
322
323 bool V8ProfilerAgentImpl::isRecording() const
324 {
325 return m_recordingCPUProfile || !m_startedProfiles.empty();
326 }
327
328 v8::CpuProfiler* V8ProfilerAgentImpl::profiler()
329 {
330 #if ENSURE_V8_VERSION(5, 4)
331 return m_profiler;
332 #else
333 return m_isolate->GetCpuProfiler();
334 #endif
335 }
336
337 } // namespace v8_inspector
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698