blob: d354aeb0469584ee27bdf94429461e262d51fd8e [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2012 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_PROFILER_CPU_PROFILER_H_
6#define V8_PROFILER_CPU_PROFILER_H_
7
Ben Murdoch61f157c2016-09-16 13:49:30 +01008#include <memory>
9
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/allocation.h"
Ben Murdochc5610432016-08-08 18:44:38 +010011#include "src/base/atomic-utils.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/base/atomicops.h"
13#include "src/base/platform/time.h"
14#include "src/compiler.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010015#include "src/isolate.h"
16#include "src/libsampler/v8-sampler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/locked-queue.h"
18#include "src/profiler/circular-queue.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010019#include "src/profiler/profiler-listener.h"
Ben Murdochc5610432016-08-08 18:44:38 +010020#include "src/profiler/tick-sample.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021
22namespace v8 {
23namespace internal {
24
25// Forward declarations.
26class CodeEntry;
27class CodeMap;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028class CpuProfile;
29class CpuProfilesCollection;
30class ProfileGenerator;
31
32#define CODE_EVENTS_TYPE_LIST(V) \
33 V(CODE_CREATION, CodeCreateEventRecord) \
34 V(CODE_MOVE, CodeMoveEventRecord) \
35 V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
36 V(CODE_DEOPT, CodeDeoptEventRecord) \
37 V(REPORT_BUILTIN, ReportBuiltinEventRecord)
38
39
40class CodeEventRecord {
41 public:
42#define DECLARE_TYPE(type, ignore) type,
43 enum Type {
44 NONE = 0,
45 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
46 NUMBER_OF_TYPES
47 };
48#undef DECLARE_TYPE
49
50 Type type;
51 mutable unsigned order;
52};
53
54
55class CodeCreateEventRecord : public CodeEventRecord {
56 public:
57 Address start;
58 CodeEntry* entry;
59 unsigned size;
60
61 INLINE(void UpdateCodeMap(CodeMap* code_map));
62};
63
64
65class CodeMoveEventRecord : public CodeEventRecord {
66 public:
67 Address from;
68 Address to;
69
70 INLINE(void UpdateCodeMap(CodeMap* code_map));
71};
72
73
74class CodeDisableOptEventRecord : public CodeEventRecord {
75 public:
76 Address start;
77 const char* bailout_reason;
78
79 INLINE(void UpdateCodeMap(CodeMap* code_map));
80};
81
82
83class CodeDeoptEventRecord : public CodeEventRecord {
84 public:
85 Address start;
86 const char* deopt_reason;
87 SourcePosition position;
Ben Murdochc5610432016-08-08 18:44:38 +010088 int deopt_id;
Ben Murdoch61f157c2016-09-16 13:49:30 +010089 void* pc;
90 int fp_to_sp_delta;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091
92 INLINE(void UpdateCodeMap(CodeMap* code_map));
93};
94
95
96class ReportBuiltinEventRecord : public CodeEventRecord {
97 public:
98 Address start;
99 Builtins::Name builtin_id;
100
101 INLINE(void UpdateCodeMap(CodeMap* code_map));
102};
103
104
105class TickSampleEventRecord {
106 public:
107 // The parameterless constructor is used when we dequeue data from
108 // the ticks buffer.
109 TickSampleEventRecord() { }
110 explicit TickSampleEventRecord(unsigned order) : order(order) { }
111
112 unsigned order;
113 TickSample sample;
114};
115
116
117class CodeEventsContainer {
118 public:
119 explicit CodeEventsContainer(
120 CodeEventRecord::Type type = CodeEventRecord::NONE) {
121 generic.type = type;
122 }
123 union {
124 CodeEventRecord generic;
125#define DECLARE_CLASS(ignore, type) type type##_;
126 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
127#undef DECLARE_TYPE
128 };
129};
130
131
132// This class implements both the profile events processor thread and
133// methods called by event producers: VM and stack sampler threads.
134class ProfilerEventsProcessor : public base::Thread {
135 public:
136 ProfilerEventsProcessor(ProfileGenerator* generator,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100137 sampler::Sampler* sampler,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 base::TimeDelta period);
139 virtual ~ProfilerEventsProcessor();
140
141 // Thread control.
142 virtual void Run();
143 void StopSynchronously();
144 INLINE(bool running()) { return !!base::NoBarrier_Load(&running_); }
145 void Enqueue(const CodeEventsContainer& event);
146
147 // Puts current stack into tick sample events buffer.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100148 void AddCurrentStack(Isolate* isolate, bool update_stats = false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 void AddDeoptStack(Isolate* isolate, Address from, int fp_to_sp_delta);
150
151 // Tick sample events are filled directly in the buffer of the circular
152 // queue (because the structure is of fixed width, but usually not all
153 // stack frame entries are filled.) This method returns a pointer to the
154 // next record of the buffer.
155 inline TickSample* StartTickSample();
156 inline void FinishTickSample();
157
158 // SamplingCircularQueue has stricter alignment requirements than a normal new
159 // can fulfil, so we need to provide our own new/delete here.
160 void* operator new(size_t size);
161 void operator delete(void* ptr);
162
163 private:
164 // Called from events processing thread (Run() method.)
165 bool ProcessCodeEvent();
166
167 enum SampleProcessingResult {
168 OneSampleProcessed,
169 FoundSampleForNextCodeEvent,
170 NoSamplesInQueue
171 };
172 SampleProcessingResult ProcessOneSample();
173
174 ProfileGenerator* generator_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100175 sampler::Sampler* sampler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 base::Atomic32 running_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100177 const base::TimeDelta period_; // Samples & code events processing period.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 LockedQueue<CodeEventsContainer> events_buffer_;
179 static const size_t kTickSampleBufferSize = 1 * MB;
180 static const size_t kTickSampleQueueLength =
181 kTickSampleBufferSize / sizeof(TickSampleEventRecord);
182 SamplingCircularQueue<TickSampleEventRecord,
183 kTickSampleQueueLength> ticks_buffer_;
184 LockedQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
Ben Murdochc5610432016-08-08 18:44:38 +0100185 base::AtomicNumber<unsigned> last_code_event_id_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 unsigned last_processed_code_event_id_;
187};
188
Ben Murdoch61f157c2016-09-16 13:49:30 +0100189class CpuProfiler : public CodeEventObserver {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000190 public:
191 explicit CpuProfiler(Isolate* isolate);
192
Ben Murdoch61f157c2016-09-16 13:49:30 +0100193 CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 ProfileGenerator* test_generator,
195 ProfilerEventsProcessor* test_processor);
196
Ben Murdochda12d292016-06-02 14:46:10 +0100197 ~CpuProfiler() override;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198
199 void set_sampling_interval(base::TimeDelta value);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100200 void CollectSample();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 void StartProfiling(const char* title, bool record_samples = false);
202 void StartProfiling(String* title, bool record_samples);
203 CpuProfile* StopProfiling(const char* title);
204 CpuProfile* StopProfiling(String* title);
205 int GetProfilesCount();
206 CpuProfile* GetProfile(int index);
207 void DeleteAllProfiles();
208 void DeleteProfile(CpuProfile* profile);
209
Ben Murdoch61f157c2016-09-16 13:49:30 +0100210 void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 // Invoked from stack sampler (thread or signal handler.)
213 inline TickSample* StartTickSample();
214 inline void FinishTickSample();
215
Ben Murdoch61f157c2016-09-16 13:49:30 +0100216 bool is_profiling() const { return is_profiling_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217
Ben Murdoch61f157c2016-09-16 13:49:30 +0100218 ProfileGenerator* generator() const { return generator_.get(); }
219 ProfilerEventsProcessor* processor() const { return processor_.get(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 Isolate* isolate() const { return isolate_; }
221
222 private:
223 void StartProcessorIfNotStarted();
224 void StopProcessorIfLastProfile(const char* title);
225 void StopProcessor();
226 void ResetProfiles();
227 void LogBuiltins();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228
Ben Murdoch61f157c2016-09-16 13:49:30 +0100229 Isolate* const isolate_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 base::TimeDelta sampling_interval_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100231 std::unique_ptr<CpuProfilesCollection> profiles_;
232 std::unique_ptr<ProfileGenerator> generator_;
233 std::unique_ptr<ProfilerEventsProcessor> processor_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 bool saved_is_logging_;
235 bool is_profiling_;
236
237 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
238};
239
240} // namespace internal
241} // namespace v8
242
243
244#endif // V8_PROFILER_CPU_PROFILER_H_