OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/inspector/v8-profiler-agent-impl.h" | 5 #include "src/inspector/v8-profiler-agent-impl.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "src/base/atomicops.h" | 9 #include "src/base/atomicops.h" |
10 #include "src/inspector/protocol/Protocol.h" | 10 #include "src/inspector/protocol/Protocol.h" |
11 #include "src/inspector/string-util.h" | 11 #include "src/inspector/string-util.h" |
12 #include "src/inspector/v8-debugger.h" | 12 #include "src/inspector/v8-debugger.h" |
13 #include "src/inspector/v8-inspector-impl.h" | 13 #include "src/inspector/v8-inspector-impl.h" |
14 #include "src/inspector/v8-inspector-session-impl.h" | 14 #include "src/inspector/v8-inspector-session-impl.h" |
15 #include "src/inspector/v8-stack-trace-impl.h" | 15 #include "src/inspector/v8-stack-trace-impl.h" |
16 | 16 |
17 #include "include/v8-profiler.h" | 17 #include "include/v8-profiler.h" |
18 | 18 |
19 namespace v8_inspector { | 19 namespace v8_inspector { |
20 | 20 |
21 namespace ProfilerAgentState { | 21 namespace ProfilerAgentState { |
22 static const char samplingInterval[] = "samplingInterval"; | 22 static const char samplingInterval[] = "samplingInterval"; |
23 static const char userInitiatedProfiling[] = "userInitiatedProfiling"; | 23 static const char userInitiatedProfiling[] = "userInitiatedProfiling"; |
24 static const char profilerEnabled[] = "profilerEnabled"; | 24 static const char profilerEnabled[] = "profilerEnabled"; |
25 static const char preciseCoverageStarted[] = "preciseCoverageStarted"; | 25 static const char preciseCoverageStarted[] = "preciseCoverageStarted"; |
| 26 static const char preciseCoverageCallCount[] = "preciseCoverageCallCount"; |
26 } | 27 } |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>> | 31 std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>> |
31 buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) { | 32 buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) { |
32 unsigned lineCount = node->GetHitLineCount(); | 33 unsigned lineCount = node->GetHitLineCount(); |
33 if (!lineCount) return nullptr; | 34 if (!lineCount) return nullptr; |
34 auto array = protocol::Array<protocol::Profiler::PositionTickInfo>::create(); | 35 auto array = protocol::Array<protocol::Profiler::PositionTickInfo>::create(); |
35 std::vector<v8::CpuProfileNode::LineTick> entries(lineCount); | 36 std::vector<v8::CpuProfileNode::LineTick> entries(lineCount); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false)) | 233 if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false)) |
233 return; | 234 return; |
234 m_enabled = true; | 235 m_enabled = true; |
235 DCHECK(!m_profiler); | 236 DCHECK(!m_profiler); |
236 if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, | 237 if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, |
237 false)) { | 238 false)) { |
238 start(); | 239 start(); |
239 } | 240 } |
240 if (m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted, | 241 if (m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted, |
241 false)) { | 242 false)) { |
242 startPreciseCoverage(); | 243 bool callCount = m_state->booleanProperty( |
| 244 ProfilerAgentState::preciseCoverageCallCount, false); |
| 245 startPreciseCoverage(Maybe<bool>(callCount)); |
243 } | 246 } |
244 } | 247 } |
245 | 248 |
246 Response V8ProfilerAgentImpl::start() { | 249 Response V8ProfilerAgentImpl::start() { |
247 if (m_recordingCPUProfile) return Response::OK(); | 250 if (m_recordingCPUProfile) return Response::OK(); |
248 if (!m_enabled) return Response::Error("Profiler is not enabled"); | 251 if (!m_enabled) return Response::Error("Profiler is not enabled"); |
249 m_recordingCPUProfile = true; | 252 m_recordingCPUProfile = true; |
250 m_frontendInitiatedProfileId = nextProfileId(); | 253 m_frontendInitiatedProfileId = nextProfileId(); |
251 startProfiling(m_frontendInitiatedProfileId); | 254 startProfiling(m_frontendInitiatedProfileId); |
252 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true); | 255 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true); |
(...skipping 10 matching lines...) Expand all Loading... |
263 stopProfiling(m_frontendInitiatedProfileId, !!profile); | 266 stopProfiling(m_frontendInitiatedProfileId, !!profile); |
264 if (profile) { | 267 if (profile) { |
265 *profile = std::move(cpuProfile); | 268 *profile = std::move(cpuProfile); |
266 if (!profile->get()) return Response::Error("Profile is not found"); | 269 if (!profile->get()) return Response::Error("Profile is not found"); |
267 } | 270 } |
268 m_frontendInitiatedProfileId = String16(); | 271 m_frontendInitiatedProfileId = String16(); |
269 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false); | 272 m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false); |
270 return Response::OK(); | 273 return Response::OK(); |
271 } | 274 } |
272 | 275 |
273 Response V8ProfilerAgentImpl::startPreciseCoverage() { | 276 Response V8ProfilerAgentImpl::startPreciseCoverage(Maybe<bool> callCount) { |
274 if (!m_enabled) return Response::Error("Profiler is not enabled"); | 277 if (!m_enabled) return Response::Error("Profiler is not enabled"); |
| 278 bool callCountValue = callCount.fromMaybe(false); |
275 m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, true); | 279 m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, true); |
276 v8::debug::Coverage::SelectMode(m_isolate, | 280 m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount, |
277 v8::debug::Coverage::kPreciseCount); | 281 callCountValue); |
| 282 v8::debug::Coverage::SelectMode( |
| 283 m_isolate, callCountValue ? v8::debug::Coverage::kPreciseCount |
| 284 : v8::debug::Coverage::kPreciseBinary); |
278 return Response::OK(); | 285 return Response::OK(); |
279 } | 286 } |
280 | 287 |
281 Response V8ProfilerAgentImpl::stopPreciseCoverage() { | 288 Response V8ProfilerAgentImpl::stopPreciseCoverage() { |
282 if (!m_enabled) return Response::Error("Profiler is not enabled"); | 289 if (!m_enabled) return Response::Error("Profiler is not enabled"); |
283 m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, false); | 290 m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, false); |
| 291 m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount, false); |
284 v8::debug::Coverage::SelectMode(m_isolate, v8::debug::Coverage::kBestEffort); | 292 v8::debug::Coverage::SelectMode(m_isolate, v8::debug::Coverage::kBestEffort); |
285 return Response::OK(); | 293 return Response::OK(); |
286 } | 294 } |
287 | 295 |
288 namespace { | 296 namespace { |
289 Response takeCoverage( | 297 Response coverageToProtocol( |
290 v8::Isolate* isolate, bool reset_count, | 298 v8::Isolate* isolate, const v8::debug::Coverage& coverage, |
291 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>* | 299 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>* |
292 out_result) { | 300 out_result) { |
293 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>> result = | 301 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>> result = |
294 protocol::Array<protocol::Profiler::ScriptCoverage>::create(); | 302 protocol::Array<protocol::Profiler::ScriptCoverage>::create(); |
295 v8::HandleScope handle_scope(isolate); | |
296 v8::debug::Coverage coverage = | |
297 v8::debug::Coverage::Collect(isolate, reset_count); | |
298 for (size_t i = 0; i < coverage.ScriptCount(); i++) { | 303 for (size_t i = 0; i < coverage.ScriptCount(); i++) { |
299 v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(i); | 304 v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(i); |
300 v8::Local<v8::debug::Script> script = script_data.GetScript(); | 305 v8::Local<v8::debug::Script> script = script_data.GetScript(); |
301 std::unique_ptr<protocol::Array<protocol::Profiler::FunctionCoverage>> | 306 std::unique_ptr<protocol::Array<protocol::Profiler::FunctionCoverage>> |
302 functions = | 307 functions = |
303 protocol::Array<protocol::Profiler::FunctionCoverage>::create(); | 308 protocol::Array<protocol::Profiler::FunctionCoverage>::create(); |
304 for (size_t j = 0; j < script_data.FunctionCount(); j++) { | 309 for (size_t j = 0; j < script_data.FunctionCount(); j++) { |
305 v8::debug::Coverage::FunctionData function_data = | 310 v8::debug::Coverage::FunctionData function_data = |
306 script_data.GetFunctionData(j); | 311 script_data.GetFunctionData(j); |
307 std::unique_ptr<protocol::Array<protocol::Profiler::CoverageRange>> | 312 std::unique_ptr<protocol::Array<protocol::Profiler::CoverageRange>> |
(...skipping 28 matching lines...) Expand all Loading... |
336 } | 341 } |
337 } // anonymous namespace | 342 } // anonymous namespace |
338 | 343 |
339 Response V8ProfilerAgentImpl::takePreciseCoverage( | 344 Response V8ProfilerAgentImpl::takePreciseCoverage( |
340 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>* | 345 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>* |
341 out_result) { | 346 out_result) { |
342 if (!m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted, | 347 if (!m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted, |
343 false)) { | 348 false)) { |
344 return Response::Error("Precise coverage has not been started."); | 349 return Response::Error("Precise coverage has not been started."); |
345 } | 350 } |
346 return takeCoverage(m_isolate, true, out_result); | 351 v8::HandleScope handle_scope(m_isolate); |
| 352 v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(m_isolate); |
| 353 return coverageToProtocol(m_isolate, coverage, out_result); |
347 } | 354 } |
348 | 355 |
349 Response V8ProfilerAgentImpl::getBestEffortCoverage( | 356 Response V8ProfilerAgentImpl::getBestEffortCoverage( |
350 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>* | 357 std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>* |
351 out_result) { | 358 out_result) { |
352 return takeCoverage(m_isolate, false, out_result); | 359 v8::HandleScope handle_scope(m_isolate); |
| 360 v8::debug::Coverage coverage = |
| 361 v8::debug::Coverage::CollectBestEffort(m_isolate); |
| 362 return coverageToProtocol(m_isolate, coverage, out_result); |
353 } | 363 } |
354 | 364 |
355 String16 V8ProfilerAgentImpl::nextProfileId() { | 365 String16 V8ProfilerAgentImpl::nextProfileId() { |
356 return String16::fromInteger( | 366 return String16::fromInteger( |
357 v8::base::NoBarrier_AtomicIncrement(&s_lastProfileId, 1)); | 367 v8::base::NoBarrier_AtomicIncrement(&s_lastProfileId, 1)); |
358 } | 368 } |
359 | 369 |
360 void V8ProfilerAgentImpl::startProfiling(const String16& title) { | 370 void V8ProfilerAgentImpl::startProfiling(const String16& title) { |
361 v8::HandleScope handleScope(m_isolate); | 371 v8::HandleScope handleScope(m_isolate); |
362 if (!m_startedProfilesCount) { | 372 if (!m_startedProfilesCount) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 return m_profiler; | 405 return m_profiler; |
396 } | 406 } |
397 | 407 |
398 bool V8ProfilerAgentImpl::idleFinished() { | 408 bool V8ProfilerAgentImpl::idleFinished() { |
399 m_idle = false; | 409 m_idle = false; |
400 if (m_profiler) m_profiler->SetIdle(m_idle); | 410 if (m_profiler) m_profiler->SetIdle(m_idle); |
401 return m_profiler; | 411 return m_profiler; |
402 } | 412 } |
403 | 413 |
404 } // namespace v8_inspector | 414 } // namespace v8_inspector |
OLD | NEW |