Line data Source code
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 : #ifndef V8_LIBSAMPLER_SAMPLER_H_
6 : #define V8_LIBSAMPLER_SAMPLER_H_
7 :
8 : #include "include/v8.h"
9 :
10 : #include "src/base/atomicops.h"
11 : #include "src/base/macros.h"
12 :
13 : namespace v8 {
14 : namespace sampler {
15 :
16 : // ----------------------------------------------------------------------------
17 : // Sampler
18 : //
19 : // A sampler periodically samples the state of the VM and optionally
20 : // (if used for profiling) the program counter and stack pointer for
21 : // the thread that created it.
22 :
23 : class Sampler {
24 : public:
25 : static const int kMaxFramesCountLog2 = 8;
26 : static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;
27 :
28 : // Initializes the Sampler support. Called once at VM startup.
29 : static void SetUp();
30 : static void TearDown();
31 :
32 : // Initialize sampler.
33 : explicit Sampler(Isolate* isolate);
34 : virtual ~Sampler();
35 :
36 : Isolate* isolate() const { return isolate_; }
37 :
38 : // Performs stack sampling.
39 : // Clients should override this method in order to do something on samples,
40 : // for example buffer samples in a queue.
41 : virtual void SampleStack(const v8::RegisterState& regs) = 0;
42 :
43 : // Start and stop sampler.
44 : void Start();
45 : void Stop();
46 :
47 : // Whether the sampling thread should use this Sampler for CPU profiling?
48 0 : bool IsProfiling() const {
49 0 : return base::Relaxed_Load(&profiling_) > 0 &&
50 0 : !base::Relaxed_Load(&has_processing_thread_);
51 : }
52 : void IncreaseProfilingDepth();
53 : void DecreaseProfilingDepth();
54 :
55 : // Whether the sampler is running (that is, consumes resources).
56 154813 : bool IsActive() const { return base::Relaxed_Load(&active_) != 0; }
57 :
58 : // CpuProfiler collects samples by calling DoSample directly
59 : // without calling Start. To keep it working, we register the sampler
60 : // with the CpuProfiler.
61 29912 : bool IsRegistered() const { return base::Relaxed_Load(®istered_) != 0; }
62 :
63 : // The sampler must be unregistered with the SamplerManager before ~Sampler()
64 : // is called. If this doesn't happen, the signal handler might interrupt
65 : // during the destructor and call DoSample(), which calls the pure virtual
66 : // function Sampler::SampleStack(), causing a crash.
67 : void UnregisterIfRegistered();
68 :
69 : void DoSample();
70 :
71 : void SetHasProcessingThread(bool value) {
72 : base::Relaxed_Store(&has_processing_thread_, value);
73 : }
74 :
75 : // Used in tests to make sure that stack sampling is performed.
76 : unsigned js_sample_count() const { return js_sample_count_; }
77 : unsigned external_sample_count() const { return external_sample_count_; }
78 : void StartCountingSamples() {
79 530 : js_sample_count_ = 0;
80 530 : external_sample_count_ = 0;
81 530 : is_counting_samples_ = true;
82 : }
83 :
84 : class PlatformData;
85 : PlatformData* platform_data() const { return data_; }
86 :
87 : protected:
88 : // Counts stack samples taken in various VM states.
89 : bool is_counting_samples_;
90 : unsigned js_sample_count_;
91 : unsigned external_sample_count_;
92 :
93 : private:
94 0 : void SetActive(bool value) { base::Relaxed_Store(&active_, value); }
95 432 : void SetRegistered(bool value) { base::Relaxed_Store(®istered_, value); }
96 :
97 : Isolate* isolate_;
98 : base::Atomic32 profiling_;
99 : base::Atomic32 has_processing_thread_;
100 : base::Atomic32 active_;
101 : base::Atomic32 registered_;
102 : PlatformData* data_; // Platform specific data.
103 : DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
104 : };
105 :
106 : } // namespace sampler
107 : } // namespace v8
108 :
109 : #endif // V8_LIBSAMPLER_SAMPLER_H_
|