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 "allocation.h"
10 #include "circular-queue.h"
11 #include "platform/time.h"
13 #include "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(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \
30 V(REPORT_BUILTIN, ReportBuiltinEventRecord)
33 class CodeEventRecord {
35 #define DECLARE_TYPE(type, ignore) type,
38 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
44 mutable unsigned order;
48 class CodeCreateEventRecord : public CodeEventRecord {
55 INLINE(void UpdateCodeMap(CodeMap* code_map));
59 class CodeMoveEventRecord : public CodeEventRecord {
64 INLINE(void UpdateCodeMap(CodeMap* code_map));
68 class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
73 INLINE(void UpdateCodeMap(CodeMap* code_map));
77 class ReportBuiltinEventRecord : public CodeEventRecord {
80 Builtins::Name builtin_id;
82 INLINE(void UpdateCodeMap(CodeMap* code_map));
86 class TickSampleEventRecord {
88 // The parameterless constructor is used when we dequeue data from
90 TickSampleEventRecord() { }
91 explicit TickSampleEventRecord(unsigned order) : order(order) { }
98 class CodeEventsContainer {
100 explicit CodeEventsContainer(
101 CodeEventRecord::Type type = CodeEventRecord::NONE) {
105 CodeEventRecord generic;
106 #define DECLARE_CLASS(ignore, type) type type##_;
107 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
113 // This class implements both the profile events processor thread and
114 // methods called by event producers: VM and stack sampler threads.
115 class ProfilerEventsProcessor : public Thread {
117 ProfilerEventsProcessor(ProfileGenerator* generator,
120 virtual ~ProfilerEventsProcessor() {}
124 void StopSynchronously();
125 INLINE(bool running()) { return running_; }
126 void Enqueue(const CodeEventsContainer& event);
128 // Puts current stack into tick sample events buffer.
129 void AddCurrentStack(Isolate* isolate);
131 // Tick sample events are filled directly in the buffer of the circular
132 // queue (because the structure is of fixed width, but usually not all
133 // stack frame entries are filled.) This method returns a pointer to the
134 // next record of the buffer.
135 inline TickSample* StartTickSample();
136 inline void FinishTickSample();
138 // SamplingCircularQueue has stricter alignment requirements than a normal new
139 // can fulfil, so we need to provide our own new/delete here.
140 void* operator new(size_t size);
141 void operator delete(void* ptr);
144 // Called from events processing thread (Run() method.)
145 bool ProcessCodeEvent();
147 enum SampleProcessingResult {
149 FoundSampleForNextCodeEvent,
152 SampleProcessingResult ProcessOneSample();
154 ProfileGenerator* generator_;
157 // Sampling period in microseconds.
158 const TimeDelta period_;
159 UnboundQueue<CodeEventsContainer> events_buffer_;
160 static const size_t kTickSampleBufferSize = 1 * MB;
161 static const size_t kTickSampleQueueLength =
162 kTickSampleBufferSize / sizeof(TickSampleEventRecord);
163 SamplingCircularQueue<TickSampleEventRecord,
164 kTickSampleQueueLength> ticks_buffer_;
165 UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
166 unsigned last_code_event_id_;
167 unsigned last_processed_code_event_id_;
171 #define PROFILE(IsolateGetter, Call) \
173 Isolate* cpu_profiler_isolate = (IsolateGetter); \
174 v8::internal::Logger* logger = cpu_profiler_isolate->logger(); \
175 CpuProfiler* cpu_profiler = cpu_profiler_isolate->cpu_profiler(); \
176 if (logger->is_logging_code_events() || cpu_profiler->is_profiling()) { \
182 class CpuProfiler : public CodeEventListener {
184 explicit CpuProfiler(Isolate* isolate);
186 CpuProfiler(Isolate* isolate,
187 CpuProfilesCollection* test_collection,
188 ProfileGenerator* test_generator,
189 ProfilerEventsProcessor* test_processor);
191 virtual ~CpuProfiler();
193 void set_sampling_interval(TimeDelta value);
194 void StartProfiling(const char* title, bool record_samples = false);
195 void StartProfiling(String* title, bool record_samples);
196 CpuProfile* StopProfiling(const char* title);
197 CpuProfile* StopProfiling(String* title);
198 int GetProfilesCount();
199 CpuProfile* GetProfile(int index);
200 void DeleteAllProfiles();
201 void DeleteProfile(CpuProfile* profile);
203 // Invoked from stack sampler (thread or signal handler.)
204 inline TickSample* StartTickSample();
205 inline void FinishTickSample();
207 // Must be called via PROFILE macro, otherwise will crash when
208 // profiling is not enabled.
209 virtual void CallbackEvent(Name* name, Address entry_point);
210 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
211 Code* code, const char* comment);
212 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
213 Code* code, Name* name);
214 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
216 SharedFunctionInfo* shared,
217 CompilationInfo* info,
219 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
221 SharedFunctionInfo* shared,
222 CompilationInfo* info,
223 Name* source, int line, int column);
224 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
225 Code* code, int args_count);
226 virtual void CodeMovingGCEvent() {}
227 virtual void CodeMoveEvent(Address from, Address to);
228 virtual void CodeDeleteEvent(Address from);
229 virtual void GetterCallbackEvent(Name* name, Address entry_point);
230 virtual void RegExpCodeCreateEvent(Code* code, String* source);
231 virtual void SetterCallbackEvent(Name* name, Address entry_point);
232 virtual void SharedFunctionInfoMoveEvent(Address from, Address to);
234 INLINE(bool is_profiling() const) { return is_profiling_; }
235 bool* is_profiling_address() {
236 return &is_profiling_;
239 ProfileGenerator* generator() const { return generator_; }
240 ProfilerEventsProcessor* processor() const { return processor_; }
241 Isolate* isolate() const { return isolate_; }
244 void StartProcessorIfNotStarted();
245 void StopProcessorIfLastProfile(const char* title);
246 void StopProcessor();
247 void ResetProfiles();
251 TimeDelta sampling_interval_;
252 CpuProfilesCollection* profiles_;
253 ProfileGenerator* generator_;
254 ProfilerEventsProcessor* processor_;
255 bool saved_is_logging_;
258 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
261 } } // namespace v8::internal
264 #endif // V8_CPU_PROFILER_H_