blob: 4dc5643aa1bc73fe8ccbcba72492e07f0d71ed2a [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Block6ded16b2010-05-10 14:33:55 +01004
5#ifndef V8_CPU_PROFILER_H_
6#define V8_CPU_PROFILER_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
9#include "src/base/atomicops.h"
10#include "src/base/platform/time.h"
11#include "src/circular-queue.h"
12#include "src/sampler.h"
13#include "src/unbound-queue.h"
Steve Block6ded16b2010-05-10 14:33:55 +010014
15namespace v8 {
16namespace internal {
17
18// Forward declarations.
19class CodeEntry;
20class CodeMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021class CompilationInfo;
Steve Block6ded16b2010-05-10 14:33:55 +010022class CpuProfile;
23class CpuProfilesCollection;
24class ProfileGenerator;
Steve Block6ded16b2010-05-10 14:33:55 +010025
Steve Block44f0eee2011-05-26 01:26:41 +010026#define CODE_EVENTS_TYPE_LIST(V) \
27 V(CODE_CREATION, CodeCreateEventRecord) \
28 V(CODE_MOVE, CodeMoveEventRecord) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029 V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
30 V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \
31 V(REPORT_BUILTIN, ReportBuiltinEventRecord)
Steve Block6ded16b2010-05-10 14:33:55 +010032
33
34class CodeEventRecord {
35 public:
36#define DECLARE_TYPE(type, ignore) type,
37 enum Type {
38 NONE = 0,
39 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
40 NUMBER_OF_TYPES
41 };
42#undef DECLARE_TYPE
43
44 Type type;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045 mutable unsigned order;
Steve Block6ded16b2010-05-10 14:33:55 +010046};
47
48
49class CodeCreateEventRecord : public CodeEventRecord {
50 public:
51 Address start;
52 CodeEntry* entry;
53 unsigned size;
Steve Block44f0eee2011-05-26 01:26:41 +010054 Address shared;
Steve Block6ded16b2010-05-10 14:33:55 +010055
56 INLINE(void UpdateCodeMap(CodeMap* code_map));
57};
58
59
60class CodeMoveEventRecord : public CodeEventRecord {
61 public:
62 Address from;
63 Address to;
64
65 INLINE(void UpdateCodeMap(CodeMap* code_map));
66};
67
68
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069class CodeDisableOptEventRecord : public CodeEventRecord {
70 public:
71 Address start;
72 const char* bailout_reason;
73
74 INLINE(void UpdateCodeMap(CodeMap* code_map));
75};
76
77
Steve Block44f0eee2011-05-26 01:26:41 +010078class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
Steve Block6ded16b2010-05-10 14:33:55 +010079 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +010080 Address from;
81 Address to;
Steve Block6ded16b2010-05-10 14:33:55 +010082
83 INLINE(void UpdateCodeMap(CodeMap* code_map));
84};
85
86
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087class ReportBuiltinEventRecord : public CodeEventRecord {
88 public:
89 Address start;
90 Builtins::Name builtin_id;
91
92 INLINE(void UpdateCodeMap(CodeMap* code_map));
93};
94
95
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000096class TickSampleEventRecord {
Steve Block6ded16b2010-05-10 14:33:55 +010097 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000098 // The parameterless constructor is used when we dequeue data from
99 // the ticks buffer.
100 TickSampleEventRecord() { }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 explicit TickSampleEventRecord(unsigned order) : order(order) { }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100102
Steve Block6ded16b2010-05-10 14:33:55 +0100103 unsigned order;
104 TickSample sample;
Steve Block6ded16b2010-05-10 14:33:55 +0100105};
106
107
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108class CodeEventsContainer {
Steve Block6ded16b2010-05-10 14:33:55 +0100109 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110 explicit CodeEventsContainer(
111 CodeEventRecord::Type type = CodeEventRecord::NONE) {
112 generic.type = type;
113 }
114 union {
Steve Block6ded16b2010-05-10 14:33:55 +0100115 CodeEventRecord generic;
116#define DECLARE_CLASS(ignore, type) type type##_;
117 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
118#undef DECLARE_TYPE
119 };
Steve Block6ded16b2010-05-10 14:33:55 +0100120};
121
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122
123// This class implements both the profile events processor thread and
124// methods called by event producers: VM and stack sampler threads.
125class ProfilerEventsProcessor : public base::Thread {
126 public:
127 ProfilerEventsProcessor(ProfileGenerator* generator,
128 Sampler* sampler,
129 base::TimeDelta period);
130 virtual ~ProfilerEventsProcessor() {}
131
132 // Thread control.
133 virtual void Run();
134 void StopSynchronously();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400135 INLINE(bool running()) { return !!base::NoBarrier_Load(&running_); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 void Enqueue(const CodeEventsContainer& event);
137
138 // Puts current stack into tick sample events buffer.
139 void AddCurrentStack(Isolate* isolate);
140
141 // Tick sample events are filled directly in the buffer of the circular
142 // queue (because the structure is of fixed width, but usually not all
143 // stack frame entries are filled.) This method returns a pointer to the
144 // next record of the buffer.
145 inline TickSample* StartTickSample();
146 inline void FinishTickSample();
147
148 // SamplingCircularQueue has stricter alignment requirements than a normal new
149 // can fulfil, so we need to provide our own new/delete here.
150 void* operator new(size_t size);
151 void operator delete(void* ptr);
152
153 private:
154 // Called from events processing thread (Run() method.)
155 bool ProcessCodeEvent();
156
157 enum SampleProcessingResult {
158 OneSampleProcessed,
159 FoundSampleForNextCodeEvent,
160 NoSamplesInQueue
161 };
162 SampleProcessingResult ProcessOneSample();
163
164 ProfileGenerator* generator_;
165 Sampler* sampler_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400166 base::Atomic32 running_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 // Sampling period in microseconds.
168 const base::TimeDelta period_;
169 UnboundQueue<CodeEventsContainer> events_buffer_;
170 static const size_t kTickSampleBufferSize = 1 * MB;
171 static const size_t kTickSampleQueueLength =
172 kTickSampleBufferSize / sizeof(TickSampleEventRecord);
173 SamplingCircularQueue<TickSampleEventRecord,
174 kTickSampleQueueLength> ticks_buffer_;
175 UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
176 unsigned last_code_event_id_;
177 unsigned last_processed_code_event_id_;
178};
Steve Block6ded16b2010-05-10 14:33:55 +0100179
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181#define PROFILE(IsolateGetter, Call) \
182 do { \
183 Isolate* cpu_profiler_isolate = (IsolateGetter); \
184 v8::internal::Logger* logger = cpu_profiler_isolate->logger(); \
185 CpuProfiler* cpu_profiler = cpu_profiler_isolate->cpu_profiler(); \
186 if (logger->is_logging_code_events() || cpu_profiler->is_profiling()) { \
187 logger->Call; \
188 } \
Steve Block6ded16b2010-05-10 14:33:55 +0100189 } while (false)
Steve Block6ded16b2010-05-10 14:33:55 +0100190
191
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192class CpuProfiler : public CodeEventListener {
Steve Block6ded16b2010-05-10 14:33:55 +0100193 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 explicit CpuProfiler(Isolate* isolate);
Steve Block6ded16b2010-05-10 14:33:55 +0100195
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 CpuProfiler(Isolate* isolate,
197 CpuProfilesCollection* test_collection,
198 ProfileGenerator* test_generator,
199 ProfilerEventsProcessor* test_processor);
200
201 virtual ~CpuProfiler();
202
203 void set_sampling_interval(base::TimeDelta value);
204 void StartProfiling(const char* title, bool record_samples = false);
205 void StartProfiling(String* title, bool record_samples);
206 CpuProfile* StopProfiling(const char* title);
207 CpuProfile* StopProfiling(String* title);
208 int GetProfilesCount();
209 CpuProfile* GetProfile(int index);
210 void DeleteAllProfiles();
211 void DeleteProfile(CpuProfile* profile);
Steve Block6ded16b2010-05-10 14:33:55 +0100212
213 // Invoked from stack sampler (thread or signal handler.)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 inline TickSample* StartTickSample();
215 inline void FinishTickSample();
Steve Block6ded16b2010-05-10 14:33:55 +0100216
217 // Must be called via PROFILE macro, otherwise will crash when
218 // profiling is not enabled.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 virtual void CallbackEvent(Name* name, Address entry_point);
220 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
221 Code* code, const char* comment);
222 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
223 Code* code, Name* name);
224 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
225 SharedFunctionInfo* shared,
226 CompilationInfo* info, Name* script_name);
227 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
228 SharedFunctionInfo* shared,
229 CompilationInfo* info, Name* script_name,
230 int line, int column);
231 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
232 Code* code, int args_count);
233 virtual void CodeMovingGCEvent() {}
234 virtual void CodeMoveEvent(Address from, Address to);
235 virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
236 virtual void CodeDeleteEvent(Address from);
237 virtual void GetterCallbackEvent(Name* name, Address entry_point);
238 virtual void RegExpCodeCreateEvent(Code* code, String* source);
239 virtual void SetterCallbackEvent(Name* name, Address entry_point);
240 virtual void SharedFunctionInfoMoveEvent(Address from, Address to);
Steve Block44f0eee2011-05-26 01:26:41 +0100241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 INLINE(bool is_profiling() const) { return is_profiling_; }
243 bool* is_profiling_address() {
244 return &is_profiling_;
Steve Block6ded16b2010-05-10 14:33:55 +0100245 }
246
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 ProfileGenerator* generator() const { return generator_; }
248 ProfilerEventsProcessor* processor() const { return processor_; }
249 Isolate* isolate() const { return isolate_; }
250
Steve Block6ded16b2010-05-10 14:33:55 +0100251 private:
Steve Block6ded16b2010-05-10 14:33:55 +0100252 void StartProcessorIfNotStarted();
Iain Merrick75681382010-08-19 15:07:18 +0100253 void StopProcessorIfLastProfile(const char* title);
Steve Block44f0eee2011-05-26 01:26:41 +0100254 void StopProcessor();
255 void ResetProfiles();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 void LogBuiltins();
Steve Block6ded16b2010-05-10 14:33:55 +0100257
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 Isolate* isolate_;
259 base::TimeDelta sampling_interval_;
Steve Block6ded16b2010-05-10 14:33:55 +0100260 CpuProfilesCollection* profiles_;
Steve Block6ded16b2010-05-10 14:33:55 +0100261 ProfileGenerator* generator_;
262 ProfilerEventsProcessor* processor_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 bool saved_is_logging_;
264 bool is_profiling_;
Steve Block6ded16b2010-05-10 14:33:55 +0100265
Steve Block6ded16b2010-05-10 14:33:55 +0100266 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
267};
268
269} } // namespace v8::internal
270
271
272#endif // V8_CPU_PROFILER_H_