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
13namespace v8 {
14namespace 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
23class 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  bool IsProfiling() const {
49    return base::NoBarrier_Load(&profiling_) > 0 &&
50        !base::NoBarrier_Load(&has_processing_thread_);
51  }
52  void IncreaseProfilingDepth();
53  void DecreaseProfilingDepth();
54
55  // Whether the sampler is running (that is, consumes resources).
56  bool IsActive() const { return base::NoBarrier_Load(&active_); }
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  bool IsRegistered() const { return base::NoBarrier_Load(&registered_); }
62
63  void DoSample();
64
65  void SetHasProcessingThread(bool value) {
66    base::NoBarrier_Store(&has_processing_thread_, value);
67  }
68
69  // Used in tests to make sure that stack sampling is performed.
70  unsigned js_sample_count() const { return js_sample_count_; }
71  unsigned external_sample_count() const { return external_sample_count_; }
72  void StartCountingSamples() {
73    js_sample_count_ = 0;
74    external_sample_count_ = 0;
75    is_counting_samples_ = true;
76  }
77
78  class PlatformData;
79  PlatformData* platform_data() const { return data_; }
80
81 protected:
82  // Counts stack samples taken in various VM states.
83  bool is_counting_samples_;
84  unsigned js_sample_count_;
85  unsigned external_sample_count_;
86
87 private:
88  void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
89  void SetRegistered(bool value) { base::NoBarrier_Store(&registered_, value); }
90
91  Isolate* isolate_;
92  base::Atomic32 profiling_;
93  base::Atomic32 has_processing_thread_;
94  base::Atomic32 active_;
95  base::Atomic32 registered_;
96  PlatformData* data_;  // Platform specific data.
97  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
98};
99
100}  // namespace sampler
101}  // namespace v8
102
103#endif  // V8_LIBSAMPLER_SAMPLER_H_
104