1 // Copyright 2016 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/profiler/tracing-cpu-profiler.h"
6 
7 #include "src/profiler/cpu-profiler.h"
8 #include "src/tracing/trace-event.h"
9 #include "src/v8.h"
10 
11 #define PROFILER_TRACE_CATEGORY_ENABLED(cat) \
12   (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT(cat)))
13 
14 namespace v8 {
15 
Create(v8::Isolate * isolate)16 std::unique_ptr<TracingCpuProfiler> TracingCpuProfiler::Create(
17     v8::Isolate* isolate) {
18   return std::unique_ptr<TracingCpuProfiler>(
19       new internal::TracingCpuProfilerImpl(
20           reinterpret_cast<internal::Isolate*>(isolate)));
21 }
22 
23 namespace internal {
24 
TracingCpuProfilerImpl(Isolate * isolate)25 TracingCpuProfilerImpl::TracingCpuProfilerImpl(Isolate* isolate)
26     : isolate_(isolate), profiling_enabled_(false) {
27   // Make sure tracing system notices profiler categories.
28   PROFILER_TRACE_CATEGORY_ENABLED("v8.cpu_profiler");
29   PROFILER_TRACE_CATEGORY_ENABLED("v8.cpu_profiler.hires");
30   V8::GetCurrentPlatform()->AddTraceStateObserver(this);
31 }
32 
~TracingCpuProfilerImpl()33 TracingCpuProfilerImpl::~TracingCpuProfilerImpl() {
34   StopProfiling();
35   V8::GetCurrentPlatform()->RemoveTraceStateObserver(this);
36 }
37 
OnTraceEnabled()38 void TracingCpuProfilerImpl::OnTraceEnabled() {
39   if (!PROFILER_TRACE_CATEGORY_ENABLED("v8.cpu_profiler")) return;
40   profiling_enabled_ = true;
41   isolate_->RequestInterrupt(
42       [](v8::Isolate*, void* data) {
43         reinterpret_cast<TracingCpuProfilerImpl*>(data)->StartProfiling();
44       },
45       this);
46 }
47 
OnTraceDisabled()48 void TracingCpuProfilerImpl::OnTraceDisabled() {
49   base::LockGuard<base::Mutex> lock(&mutex_);
50   if (!profiling_enabled_) return;
51   profiling_enabled_ = false;
52   isolate_->RequestInterrupt(
53       [](v8::Isolate*, void* data) {
54         reinterpret_cast<TracingCpuProfilerImpl*>(data)->StopProfiling();
55       },
56       this);
57 }
58 
StartProfiling()59 void TracingCpuProfilerImpl::StartProfiling() {
60   base::LockGuard<base::Mutex> lock(&mutex_);
61   if (!profiling_enabled_ || profiler_) return;
62   int sampling_interval_us =
63       PROFILER_TRACE_CATEGORY_ENABLED("v8.cpu_profiler.hires") ? 100 : 1000;
64   profiler_.reset(new CpuProfiler(isolate_));
65   profiler_->set_sampling_interval(
66       base::TimeDelta::FromMicroseconds(sampling_interval_us));
67   profiler_->StartProfiling("", true);
68 }
69 
StopProfiling()70 void TracingCpuProfilerImpl::StopProfiling() {
71   base::LockGuard<base::Mutex> lock(&mutex_);
72   if (!profiler_) return;
73   profiler_->StopProfiling("");
74   profiler_.reset();
75 }
76 
77 }  // namespace internal
78 }  // namespace v8
79