1 // 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.
5 #ifndef V8_CPU_PROFILER_H_
6 #define V8_CPU_PROFILER_H_
8 #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"
18 // Forward declarations.
21 class CompilationInfo;
23 class CpuProfilesCollection;
24 class ProfileGenerator;
26 #define CODE_EVENTS_TYPE_LIST(V) \
27 V(CODE_CREATION, CodeCreateEventRecord) \
28 V(CODE_MOVE, CodeMoveEventRecord) \
29 V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
30 V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \
31 V(REPORT_BUILTIN, ReportBuiltinEventRecord)
34 class CodeEventRecord {
36 #define DECLARE_TYPE(type, ignore) type,
39 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
45 mutable unsigned order;
49 class CodeCreateEventRecord : public CodeEventRecord {
56 INLINE(void UpdateCodeMap(CodeMap* code_map));
60 class CodeMoveEventRecord : public CodeEventRecord {
65 INLINE(void UpdateCodeMap(CodeMap* code_map));
69 class CodeDisableOptEventRecord : public CodeEventRecord {
72 const char* bailout_reason;
74 INLINE(void UpdateCodeMap(CodeMap* code_map));
78 class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
83 INLINE(void UpdateCodeMap(CodeMap* code_map));
87 class ReportBuiltinEventRecord : public CodeEventRecord {
90 Builtins::Name builtin_id;
92 INLINE(void UpdateCodeMap(CodeMap* code_map));
96 class TickSampleEventRecord {
98 // The parameterless constructor is used when we dequeue data from
100 TickSampleEventRecord() { }
101 explicit TickSampleEventRecord(unsigned order) : order(order) { }
108 class CodeEventsContainer {
110 explicit CodeEventsContainer(
111 CodeEventRecord::Type type = CodeEventRecord::NONE) {
115 CodeEventRecord generic;
116 #define DECLARE_CLASS(ignore, type) type type##_;
117 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
123 // This class implements both the profile events processor thread and
124 // methods called by event producers: VM and stack sampler threads.
125 class ProfilerEventsProcessor : public base::Thread {
127 ProfilerEventsProcessor(ProfileGenerator* generator,
129 base::TimeDelta period);
130 virtual ~ProfilerEventsProcessor() {}
134 void StopSynchronously();
135 INLINE(bool running()) { return running_; }
136 void Enqueue(const CodeEventsContainer& event);
138 // Puts current stack into tick sample events buffer.
139 void AddCurrentStack(Isolate* isolate);
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();
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);
154 // Called from events processing thread (Run() method.)
155 bool ProcessCodeEvent();
157 enum SampleProcessingResult {
159 FoundSampleForNextCodeEvent,
162 SampleProcessingResult ProcessOneSample();
164 ProfileGenerator* generator_;
167 // 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_;
181 #define PROFILE(IsolateGetter, Call) \
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()) { \
192 class CpuProfiler : public CodeEventListener {
194 explicit CpuProfiler(Isolate* isolate);
196 CpuProfiler(Isolate* isolate,
197 CpuProfilesCollection* test_collection,
198 ProfileGenerator* test_generator,
199 ProfilerEventsProcessor* test_processor);
201 virtual ~CpuProfiler();
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);
213 // Invoked from stack sampler (thread or signal handler.)
214 inline TickSample* StartTickSample();
215 inline void FinishTickSample();
217 // Must be called via PROFILE macro, otherwise will crash when
218 // profiling is not enabled.
219 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);
242 INLINE(bool is_profiling() const) { return is_profiling_; }
243 bool* is_profiling_address() {
244 return &is_profiling_;
247 ProfileGenerator* generator() const { return generator_; }
248 ProfilerEventsProcessor* processor() const { return processor_; }
249 Isolate* isolate() const { return isolate_; }
252 void StartProcessorIfNotStarted();
253 void StopProcessorIfLastProfile(const char* title);
254 void StopProcessor();
255 void ResetProfiles();
259 base::TimeDelta sampling_interval_;
260 CpuProfilesCollection* profiles_;
261 ProfileGenerator* generator_;
262 ProfilerEventsProcessor* processor_;
263 bool saved_is_logging_;
266 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
269 } } // namespace v8::internal
272 #endif // V8_CPU_PROFILER_H_