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

Side by Side Diff: src/inspector/V8ProfilerAgentImpl.cpp

Issue 2292573002: [inspector] Initial import of v8_inspector. (Closed)
Patch Set: format the code, disable cpplint 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
« no previous file with comments | « src/inspector/V8ProfilerAgentImpl.h ('k') | src/inspector/V8Regex.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project 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 "src/inspector/V8ProfilerAgentImpl.h"
6
7 #include <v8-profiler.h>
8 #include "src/inspector/Atomics.h"
9 #include "src/inspector/StringUtil.h"
10 #include "src/inspector/V8Debugger.h"
11 #include "src/inspector/V8InspectorImpl.h"
12 #include "src/inspector/V8InspectorSessionImpl.h"
13 #include "src/inspector/V8StackTraceImpl.h"
14 #include "src/inspector/protocol/Protocol.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>>
32 buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) {
33 unsigned lineCount = node->GetHitLineCount();
34 if (!lineCount) return nullptr;
35 auto array = protocol::Array<protocol::Profiler::PositionTickInfo>::create();
36 std::vector<v8::CpuProfileNode::LineTick> entries(lineCount);
37 if (node->GetLineTicks(&entries[0], lineCount)) {
38 for (unsigned i = 0; i < lineCount; i++) {
39 std::unique_ptr<protocol::Profiler::PositionTickInfo> line =
40 protocol::Profiler::PositionTickInfo::create()
41 .setLine(entries[i].line)
42 .setTicks(entries[i].hit_count)
43 .build();
44 array->addItem(std::move(line));
45 }
46 }
47 return array;
48 }
49
50 std::unique_ptr<protocol::Profiler::ProfileNode> buildInspectorObjectFor(
51 v8::Isolate* isolate, const v8::CpuProfileNode* node) {
52 v8::HandleScope handleScope(isolate);
53 auto callFrame =
54 protocol::Runtime::CallFrame::create()
55 .setFunctionName(toProtocolString(node->GetFunctionName()))
56 .setScriptId(String16::fromInteger(node->GetScriptId()))
57 .setUrl(toProtocolString(node->GetScriptResourceName()))
58 .setLineNumber(node->GetLineNumber() - 1)
59 .setColumnNumber(node->GetColumnNumber() - 1)
60 .build();
61 auto result = protocol::Profiler::ProfileNode::create()
62 .setCallFrame(std::move(callFrame))
63 .setHitCount(node->GetHitCount())
64 .setId(node->GetNodeId())
65 .build();
66
67 const int childrenCount = node->GetChildrenCount();
68 if (childrenCount) {
69 auto children = protocol::Array<int>::create();
70 for (int i = 0; i < childrenCount; i++)
71 children->addItem(node->GetChild(i)->GetNodeId());
72 result->setChildren(std::move(children));
73 }
74
75 const char* deoptReason = node->GetBailoutReason();
76 if (deoptReason && deoptReason[0] && strcmp(deoptReason, "no reason"))
77 result->setDeoptReason(deoptReason);
78
79 auto positionTicks = buildInspectorObjectForPositionTicks(node);
80 if (positionTicks) result->setPositionTicks(std::move(positionTicks));
81
82 return result;
83 }
84
85 std::unique_ptr<protocol::Array<int>> buildInspectorObjectForSamples(
86 v8::CpuProfile* v8profile) {
87 auto array = protocol::Array<int>::create();
88 int count = v8profile->GetSamplesCount();
89 for (int i = 0; i < count; i++)
90 array->addItem(v8profile->GetSample(i)->GetNodeId());
91 return array;
92 }
93
94 std::unique_ptr<protocol::Array<int>> buildInspectorObjectForTimestamps(
95 v8::CpuProfile* v8profile) {
96 auto array = protocol::Array<int>::create();
97 int count = v8profile->GetSamplesCount();
98 uint64_t lastTime = v8profile->GetStartTime();
99 for (int i = 0; i < count; i++) {
100 uint64_t ts = v8profile->GetSampleTimestamp(i);
101 array->addItem(static_cast<int>(ts - lastTime));
102 lastTime = ts;
103 }
104 return array;
105 }
106
107 void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node,
108 protocol::Array<protocol::Profiler::ProfileNode>* list) {
109 list->addItem(buildInspectorObjectFor(isolate, node));
110 const int childrenCount = node->GetChildrenCount();
111 for (int i = 0; i < childrenCount; i++)
112 flattenNodesTree(isolate, node->GetChild(i), list);
113 }
114
115 std::unique_ptr<protocol::Profiler::Profile> createCPUProfile(
116 v8::Isolate* isolate, v8::CpuProfile* v8profile) {
117 auto nodes = protocol::Array<protocol::Profiler::ProfileNode>::create();
118 flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get());
119 return protocol::Profiler::Profile::create()
120 .setNodes(std::move(nodes))
121 .setStartTime(static_cast<double>(v8profile->GetStartTime()))
122 .setEndTime(static_cast<double>(v8profile->GetEndTime()))
123 .setSamples(buildInspectorObjectForSamples(v8profile))
124 .setTimeDeltas(buildInspectorObjectForTimestamps(v8profile))
125 .build();
126 }
127
128 std::unique_ptr<protocol::Debugger::Location> currentDebugLocation(
129 V8InspectorImpl* inspector) {
130 std::unique_ptr<V8StackTraceImpl> callStack =
131 inspector->debugger()->captureStackTrace(false /* fullStack */);
132 auto location = protocol::Debugger::Location::create()
133 .setScriptId(toString16(callStack->topScriptId()))
134 .setLineNumber(callStack->topLineNumber())
135 .build();
136 location->setColumnNumber(callStack->topColumnNumber());
137 return location;
138 }
139
140 volatile int s_lastProfileId = 0;
141
142 } // namespace
143
144 class V8ProfilerAgentImpl::ProfileDescriptor {
145 public:
146 ProfileDescriptor(const String16& id, const String16& title)
147 : m_id(id), m_title(title) {}
148 String16 m_id;
149 String16 m_title;
150 };
151
152 V8ProfilerAgentImpl::V8ProfilerAgentImpl(
153 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel,
154 protocol::DictionaryValue* state)
155 : m_session(session),
156 m_isolate(m_session->inspector()->isolate()),
157 m_profiler(nullptr),
158 m_state(state),
159 m_frontend(frontendChannel),
160 m_enabled(false),
161 m_recordingCPUProfile(false) {}
162
163 V8ProfilerAgentImpl::~V8ProfilerAgentImpl() {
164 #if ENSURE_V8_VERSION(5, 4)
165 if (m_profiler) m_profiler->Dispose();
166 #endif
167 }
168
169 void V8ProfilerAgentImpl::consoleProfile(const String16& title) {
170 if (!m_enabled) return;
171 String16 id = nextProfileId();
172 m_startedProfiles.push_back(ProfileDescriptor(id, title));
173 startProfiling(id);
174 m_frontend.consoleProfileStarted(
175 id, currentDebugLocation(m_session->inspector()), title);
176 }
177
178 void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) {
179 if (!m_enabled) return;
180 String16 id;
181 String16 resolvedTitle;
182 // Take last started profile if no title was passed.
183 if (title.isEmpty()) {
184 if (m_startedProfiles.empty()) return;
185 id = m_startedProfiles.back().m_id;
186 resolvedTitle = m_startedProfiles.back().m_title;
187 m_startedProfiles.pop_back();
188 } else {
189 for (size_t i = 0; i < m_startedProfiles.size(); i++) {
190 if (m_startedProfiles[i].m_title == title) {
191 resolvedTitle = title;
192 id = m_startedProfiles[i].m_id;
193 m_startedProfiles.erase(m_startedProfiles.begin() + i);
194 break;
195 }
196 }
197 if (id.isEmpty()) return;
198 }
199 std::unique_ptr<protocol::Profiler::Profile> profile =
200 stopProfiling(id, true);
201 if (!profile) return;
202 std::unique_ptr<protocol::Debugger::Location> location =
203 currentDebugLocation(m_session->inspector());
204 m_frontend.consoleProfileFinished(id, std::move(location), std::move(profile),
205 resolvedTitle);
206 }
207
208 void V8ProfilerAgentImpl::enable(ErrorString*) {
209 if (m_enabled) return;
210 m_enabled = true;
211 #if ENSURE_V8_VERSION(5, 4)
212 DCHECK(!m_profiler);
213 m_profiler = v8::CpuProfiler::New(m_isolate);
214 #endif
215 m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
216 }
217
218 void V8ProfilerAgentImpl::disable(ErrorString* errorString) {
219 if (!m_enabled) return;
220 for (size_t i = m_startedProfiles.size(); i > 0; --i)
221 stopProfiling(m_startedProfiles[i - 1].m_id, false);
222 m_startedProfiles.clear();
223 stop(nullptr, nullptr);
224 #if ENSURE_V8_VERSION(5, 4)
225 m_profiler->Dispose();
226 m_profiler = nullptr;
227 #endif
228 m_enabled = false;
229 m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
230 }
231
232 void V8ProfilerAgentImpl::setSamplingInterval(ErrorString* error,
233 int interval) {
234 if (m_recordingCPUProfile) {
235 *error = "Cannot change sampling interval when profiling.";
236 return;
237 }
238 m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
239 profiler()->SetSamplingInterval(interval);
240 }
241
242 void V8ProfilerAgentImpl::restore() {
243 DCHECK(!m_enabled);
244 if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false))
245 return;
246 m_enabled = true;
247 #if ENSURE_V8_VERSION(5, 4)
248 DCHECK(!m_profiler);
249 m_profiler = v8::CpuProfiler::New(m_isolate);
250 #endif
251 int interval = 0;
252 m_state->getInteger(ProfilerAgentState::samplingInterval, &interval);
253 if (interval) profiler()->SetSamplingInterval(interval);
254 if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling,
255 false)) {
256 ErrorString error;
257 start(&error);
258 }
259 }
260
261 void V8ProfilerAgentImpl::start(ErrorString* error) {
262 if (m_recordingCPUProfile) return;
263 if (!m_enabled) {
264 *error = "Profiler is not enabled";
265 return;
266 }
267 m_recordingCPUProfile = true;
268 m_frontendInitiatedProfileId = nextProfileId();
269 startProfiling(m_frontendInitiatedProfileId);
270 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
271 }
272
273 void V8ProfilerAgentImpl::stop(
274 ErrorString* errorString,
275 std::unique_ptr<protocol::Profiler::Profile>* profile) {
276 if (!m_recordingCPUProfile) {
277 if (errorString) *errorString = "No recording profiles found";
278 return;
279 }
280 m_recordingCPUProfile = false;
281 std::unique_ptr<protocol::Profiler::Profile> cpuProfile =
282 stopProfiling(m_frontendInitiatedProfileId, !!profile);
283 if (profile) {
284 *profile = std::move(cpuProfile);
285 if (!profile->get() && errorString) *errorString = "Profile is not found";
286 }
287 m_frontendInitiatedProfileId = String16();
288 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
289 }
290
291 String16 V8ProfilerAgentImpl::nextProfileId() {
292 return String16::fromInteger(atomicIncrement(&s_lastProfileId));
293 }
294
295 void V8ProfilerAgentImpl::startProfiling(const String16& title) {
296 v8::HandleScope handleScope(m_isolate);
297 profiler()->StartProfiling(toV8String(m_isolate, title), true);
298 }
299
300 std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling(
301 const String16& title, bool serialize) {
302 v8::HandleScope handleScope(m_isolate);
303 v8::CpuProfile* profile =
304 profiler()->StopProfiling(toV8String(m_isolate, title));
305 if (!profile) return nullptr;
306 std::unique_ptr<protocol::Profiler::Profile> result;
307 if (serialize) result = createCPUProfile(m_isolate, profile);
308 profile->Delete();
309 return result;
310 }
311
312 bool V8ProfilerAgentImpl::isRecording() const {
313 return m_recordingCPUProfile || !m_startedProfiles.empty();
314 }
315
316 v8::CpuProfiler* V8ProfilerAgentImpl::profiler() {
317 #if ENSURE_V8_VERSION(5, 4)
318 return m_profiler;
319 #else
320 return m_isolate->GetCpuProfiler();
321 #endif
322 }
323
324 } // namespace v8_inspector
OLDNEW
« no previous file with comments | « src/inspector/V8ProfilerAgentImpl.h ('k') | src/inspector/V8Regex.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698