Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / v8 / src / cpu-profiler.h
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.
4
5 #ifndef V8_CPU_PROFILER_H_
6 #define V8_CPU_PROFILER_H_
7
8 #include "allocation.h"
9 #include "atomicops.h"
10 #include "circular-queue.h"
11 #include "platform/time.h"
12 #include "sampler.h"
13 #include "unbound-queue.h"
14
15 namespace v8 {
16 namespace internal {
17
18 // Forward declarations.
19 class CodeEntry;
20 class CodeMap;
21 class CompilationInfo;
22 class CpuProfile;
23 class CpuProfilesCollection;
24 class ProfileGenerator;
25
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)
31
32
33 class CodeEventRecord {
34  public:
35 #define DECLARE_TYPE(type, ignore) type,
36   enum Type {
37     NONE = 0,
38     CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
39     NUMBER_OF_TYPES
40   };
41 #undef DECLARE_TYPE
42
43   Type type;
44   mutable unsigned order;
45 };
46
47
48 class CodeCreateEventRecord : public CodeEventRecord {
49  public:
50   Address start;
51   CodeEntry* entry;
52   unsigned size;
53   Address shared;
54
55   INLINE(void UpdateCodeMap(CodeMap* code_map));
56 };
57
58
59 class CodeMoveEventRecord : public CodeEventRecord {
60  public:
61   Address from;
62   Address to;
63
64   INLINE(void UpdateCodeMap(CodeMap* code_map));
65 };
66
67
68 class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
69  public:
70   Address from;
71   Address to;
72
73   INLINE(void UpdateCodeMap(CodeMap* code_map));
74 };
75
76
77 class ReportBuiltinEventRecord : public CodeEventRecord {
78  public:
79   Address start;
80   Builtins::Name builtin_id;
81
82   INLINE(void UpdateCodeMap(CodeMap* code_map));
83 };
84
85
86 class TickSampleEventRecord {
87  public:
88   // The parameterless constructor is used when we dequeue data from
89   // the ticks buffer.
90   TickSampleEventRecord() { }
91   explicit TickSampleEventRecord(unsigned order) : order(order) { }
92
93   unsigned order;
94   TickSample sample;
95 };
96
97
98 class CodeEventsContainer {
99  public:
100   explicit CodeEventsContainer(
101       CodeEventRecord::Type type = CodeEventRecord::NONE) {
102     generic.type = type;
103   }
104   union  {
105     CodeEventRecord generic;
106 #define DECLARE_CLASS(ignore, type) type type##_;
107     CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
108 #undef DECLARE_TYPE
109   };
110 };
111
112
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 {
116  public:
117   ProfilerEventsProcessor(ProfileGenerator* generator,
118                           Sampler* sampler,
119                           TimeDelta period);
120   virtual ~ProfilerEventsProcessor() {}
121
122   // Thread control.
123   virtual void Run();
124   void StopSynchronously();
125   INLINE(bool running()) { return running_; }
126   void Enqueue(const CodeEventsContainer& event);
127
128   // Puts current stack into tick sample events buffer.
129   void AddCurrentStack(Isolate* isolate);
130
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();
137
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);
142
143  private:
144   // Called from events processing thread (Run() method.)
145   bool ProcessCodeEvent();
146
147   enum SampleProcessingResult {
148     OneSampleProcessed,
149     FoundSampleForNextCodeEvent,
150     NoSamplesInQueue
151   };
152   SampleProcessingResult ProcessOneSample();
153
154   ProfileGenerator* generator_;
155   Sampler* sampler_;
156   bool running_;
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_;
168 };
169
170
171 #define PROFILE(IsolateGetter, Call)                                        \
172   do {                                                                      \
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()) { \
177       logger->Call;                                                         \
178     }                                                                       \
179   } while (false)
180
181
182 class CpuProfiler : public CodeEventListener {
183  public:
184   explicit CpuProfiler(Isolate* isolate);
185
186   CpuProfiler(Isolate* isolate,
187               CpuProfilesCollection* test_collection,
188               ProfileGenerator* test_generator,
189               ProfilerEventsProcessor* test_processor);
190
191   virtual ~CpuProfiler();
192
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);
202
203   // Invoked from stack sampler (thread or signal handler.)
204   inline TickSample* StartTickSample();
205   inline void FinishTickSample();
206
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,
215                                Code* code,
216                                SharedFunctionInfo* shared,
217                                CompilationInfo* info,
218                                Name* name);
219   virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
220                                Code* code,
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);
233
234   INLINE(bool is_profiling() const) { return is_profiling_; }
235   bool* is_profiling_address() {
236     return &is_profiling_;
237   }
238
239   ProfileGenerator* generator() const { return generator_; }
240   ProfilerEventsProcessor* processor() const { return processor_; }
241   Isolate* isolate() const { return isolate_; }
242
243  private:
244   void StartProcessorIfNotStarted();
245   void StopProcessorIfLastProfile(const char* title);
246   void StopProcessor();
247   void ResetProfiles();
248   void LogBuiltins();
249
250   Isolate* isolate_;
251   TimeDelta sampling_interval_;
252   CpuProfilesCollection* profiles_;
253   ProfileGenerator* generator_;
254   ProfilerEventsProcessor* processor_;
255   bool saved_is_logging_;
256   bool is_profiling_;
257
258   DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
259 };
260
261 } }  // namespace v8::internal
262
263
264 #endif  // V8_CPU_PROFILER_H_