v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
sampler.h
Go to the documentation of this file.
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 <atomic>
9#include <memory>
10#include <unordered_map>
11#include <vector>
12
14#include "src/base/macros.h"
15
16#if V8_OS_POSIX && !V8_OS_CYGWIN && !V8_OS_FUCHSIA
17#define USE_SIGNALS
18#endif
19
20namespace v8 {
21
22class Isolate;
23struct RegisterState;
24
25namespace sampler {
26
27// ----------------------------------------------------------------------------
28// Sampler
29//
30// A sampler periodically samples the state of the VM and optionally
31// (if used for profiling) the program counter and stack pointer for
32// the thread that created it.
33
35 public:
36 static const int kMaxFramesCountLog2 = 8;
37 static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;
38
39 // Initialize sampler.
40 explicit Sampler(Isolate* isolate);
41 virtual ~Sampler();
42
43 Isolate* isolate() const { return isolate_; }
44
45 // Performs stack sampling.
46 // Clients should override this method in order to do something on samples,
47 // for example buffer samples in a queue.
48 virtual void SampleStack(const v8::RegisterState& regs) = 0;
49
50 // Start and stop sampler.
51 void Start();
52 void Stop();
53
54 // Whether the sampler is running (start has been called).
55 bool IsActive() const { return active_.load(std::memory_order_relaxed); }
56
57 // Returns true and consumes the pending sample bit if a sample should be
58 // dispatched to this sampler.
60 return record_sample_.exchange(false, std::memory_order_relaxed);
61 }
62
63 void DoSample();
64
65 // Used in tests to make sure that stack sampling is performed.
66 unsigned js_sample_count() const { return js_sample_count_; }
67 unsigned external_sample_count() const { return external_sample_count_; }
69 js_sample_count_ = 0;
70 external_sample_count_ = 0;
71 is_counting_samples_ = true;
72 }
73
74 class PlatformData;
75 PlatformData* platform_data() const { return data_.get(); }
76
77 protected:
78 // Counts stack samples taken in various VM states.
79 bool is_counting_samples_ = false;
80 unsigned js_sample_count_ = 0;
81 unsigned external_sample_count_ = 0;
82
83 void SetActive(bool value) {
84 active_.store(value, std::memory_order_relaxed);
85 }
86
88 record_sample_.store(true, std::memory_order_relaxed);
89 }
90
92 std::atomic_bool active_{false};
93 std::atomic_bool record_sample_{false};
94 std::unique_ptr<PlatformData> data_; // Platform specific data.
96};
97
98#ifdef USE_SIGNALS
99
100using AtomicMutex = std::atomic_bool;
101
102// A helper that uses an std::atomic_bool to create a lock that is obtained on
103// construction and released on destruction.
104class V8_EXPORT_PRIVATE V8_NODISCARD AtomicGuard {
105 public:
106 // Attempt to obtain the lock represented by |atomic|. |is_blocking|
107 // determines whether we will block to obtain the lock, or only make one
108 // attempt to gain the lock and then stop. If we fail to gain the lock,
109 // is_success will be false.
110 explicit AtomicGuard(AtomicMutex* atomic, bool is_blocking = true);
111
112 // Releases the lock represented by atomic, if it is held by this guard.
113 ~AtomicGuard();
114
115 // Whether the lock was successfully obtained in the constructor. This will
116 // always be true if is_blocking was true.
117 bool is_success() const;
118
119 private:
120 AtomicMutex* const atomic_;
121 bool is_success_;
122};
123
124// SamplerManager keeps a list of Samplers per thread, and allows the caller to
125// take a sample for every Sampler on the current thread.
126class V8_EXPORT_PRIVATE SamplerManager {
127 public:
128 using SamplerList = std::vector<Sampler*>;
129
130 SamplerManager(const SamplerManager&) = delete;
131 SamplerManager& operator=(const SamplerManager&) = delete;
132
133 // Add |sampler| to the map if it is not already present.
134 void AddSampler(Sampler* sampler);
135
136 // If |sampler| exists in the map, remove it and delete the SamplerList if
137 // |sampler| was the last sampler in the list.
138 void RemoveSampler(Sampler* sampler);
139
140 // Take a sample for every sampler on the current thread. This function can
141 // return without taking samples if AddSampler or RemoveSampler are being
142 // concurrently called on any thread.
143 void DoSample(const v8::RegisterState& state);
144
145 // Get the lazily instantiated, global SamplerManager instance.
146 static SamplerManager* instance();
147
148 private:
149 SamplerManager() = default;
150 // Must be a friend so that it can access the private constructor for the
151 // global lazy instance.
152 friend class base::LeakyObject<SamplerManager>;
153
154 std::unordered_map<int, SamplerList> sampler_map_;
155 AtomicMutex samplers_access_counter_{false};
156};
157
158#endif // USE_SIGNALS
159
160} // namespace sampler
161} // namespace v8
162
163#endif // V8_LIBSAMPLER_SAMPLER_H_
Isolate * isolate_
uint8_t data_[MAX_STACK_LENGTH]
bool IsActive() const
Definition sampler.h:55
unsigned js_sample_count() const
Definition sampler.h:66
Isolate * isolate() const
Definition sampler.h:43
void SetShouldRecordSample()
Definition sampler.h:87
DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler)
void SetActive(bool value)
Definition sampler.h:83
virtual void SampleStack(const v8::RegisterState &regs)=0
bool ShouldRecordSample()
Definition sampler.h:59
std::unique_ptr< PlatformData > data_
Definition sampler.h:94
PlatformData * platform_data() const
Definition sampler.h:75
unsigned external_sample_count() const
Definition sampler.h:67
void StartCountingSamples()
Definition sampler.h:68
Isolate * isolate_
Definition sampler.h:91
bool active_
Definition cpp-heap.cc:596
base::PointerWithPayload< void, RegisterStateFlags, 2 > RegisterState
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_NODISCARD
Definition v8config.h:693