blob: 03b81764851cea6881e33a4d42cdbd130ecaab51 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_CPU_PROFILER_H_
29#define V8_CPU_PROFILER_H_
30
31#ifdef ENABLE_LOGGING_AND_PROFILING
32
33#include "circular-queue.h"
Leon Clarkef7060e22010-06-03 12:02:55 +010034#include "unbound-queue.h"
Steve Block6ded16b2010-05-10 14:33:55 +010035
36namespace v8 {
37namespace internal {
38
39// Forward declarations.
40class CodeEntry;
41class CodeMap;
42class CpuProfile;
43class CpuProfilesCollection;
44class ProfileGenerator;
Leon Clarkef7060e22010-06-03 12:02:55 +010045class TokenEnumerator;
Steve Block6ded16b2010-05-10 14:33:55 +010046
47#define CODE_EVENTS_TYPE_LIST(V) \
48 V(CODE_CREATION, CodeCreateEventRecord) \
49 V(CODE_MOVE, CodeMoveEventRecord) \
50 V(CODE_DELETE, CodeDeleteEventRecord) \
51 V(CODE_ALIAS, CodeAliasEventRecord)
52
53
54class CodeEventRecord {
55 public:
56#define DECLARE_TYPE(type, ignore) type,
57 enum Type {
58 NONE = 0,
59 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
60 NUMBER_OF_TYPES
61 };
62#undef DECLARE_TYPE
63
64 Type type;
65 unsigned order;
66};
67
68
69class CodeCreateEventRecord : public CodeEventRecord {
70 public:
71 Address start;
72 CodeEntry* entry;
73 unsigned size;
74
75 INLINE(void UpdateCodeMap(CodeMap* code_map));
76};
77
78
79class CodeMoveEventRecord : public CodeEventRecord {
80 public:
81 Address from;
82 Address to;
83
84 INLINE(void UpdateCodeMap(CodeMap* code_map));
85};
86
87
88class CodeDeleteEventRecord : public CodeEventRecord {
89 public:
90 Address start;
91
92 INLINE(void UpdateCodeMap(CodeMap* code_map));
93};
94
95
96class CodeAliasEventRecord : public CodeEventRecord {
97 public:
Steve Block6ded16b2010-05-10 14:33:55 +010098 Address start;
Leon Clarkef7060e22010-06-03 12:02:55 +010099 CodeEntry* entry;
100 Address code_start;
Steve Block6ded16b2010-05-10 14:33:55 +0100101
102 INLINE(void UpdateCodeMap(CodeMap* code_map));
103};
104
105
106class TickSampleEventRecord BASE_EMBEDDED {
107 public:
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100108 TickSampleEventRecord()
109 : filler(1) {
110 ASSERT(filler != SamplingCircularQueue::kClear);
111 }
112
Steve Block6ded16b2010-05-10 14:33:55 +0100113 // The first machine word of a TickSampleEventRecord must not ever
114 // become equal to SamplingCircularQueue::kClear. As both order and
115 // TickSample's first field are not reliable in this sense (order
116 // can overflow, TickSample can have all fields reset), we are
117 // forced to use an artificial filler field.
118 int filler;
119 unsigned order;
120 TickSample sample;
121
122 static TickSampleEventRecord* cast(void* value) {
123 return reinterpret_cast<TickSampleEventRecord*>(value);
124 }
125
126 INLINE(static TickSampleEventRecord* init(void* value));
Steve Block6ded16b2010-05-10 14:33:55 +0100127};
128
129
130// This class implements both the profile events processor thread and
131// methods called by event producers: VM and stack sampler threads.
132class ProfilerEventsProcessor : public Thread {
133 public:
134 explicit ProfilerEventsProcessor(ProfileGenerator* generator);
135 virtual ~ProfilerEventsProcessor() { }
136
137 // Thread control.
138 virtual void Run();
139 inline void Stop() { running_ = false; }
140 INLINE(bool running()) { return running_; }
141
142 // Events adding methods. Called by VM threads.
143 void CallbackCreateEvent(Logger::LogEventsAndTags tag,
144 const char* prefix, String* name,
145 Address start);
146 void CodeCreateEvent(Logger::LogEventsAndTags tag,
147 String* name,
148 String* resource_name, int line_number,
149 Address start, unsigned size);
150 void CodeCreateEvent(Logger::LogEventsAndTags tag,
151 const char* name,
152 Address start, unsigned size);
153 void CodeCreateEvent(Logger::LogEventsAndTags tag,
154 int args_count,
155 Address start, unsigned size);
156 void CodeMoveEvent(Address from, Address to);
157 void CodeDeleteEvent(Address from);
Leon Clarkef7060e22010-06-03 12:02:55 +0100158 void FunctionCreateEvent(Address alias, Address start, int security_token_id);
Steve Block6ded16b2010-05-10 14:33:55 +0100159 void FunctionMoveEvent(Address from, Address to);
160 void FunctionDeleteEvent(Address from);
161 void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
162 const char* prefix, String* name,
163 Address start, unsigned size);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100164 // Puts current stack into tick sample events buffer.
165 void AddCurrentStack();
Steve Block6ded16b2010-05-10 14:33:55 +0100166
167 // Tick sample events are filled directly in the buffer of the circular
168 // queue (because the structure is of fixed width, but usually not all
169 // stack frame entries are filled.) This method returns a pointer to the
170 // next record of the buffer.
171 INLINE(TickSample* TickSampleEvent());
172
173 private:
174 union CodeEventsContainer {
175 CodeEventRecord generic;
176#define DECLARE_CLASS(ignore, type) type type##_;
177 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
178#undef DECLARE_TYPE
179 };
180
181 // Called from events processing thread (Run() method.)
182 bool ProcessCodeEvent(unsigned* dequeue_order);
183 bool ProcessTicks(unsigned dequeue_order);
184
185 INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
186
187 ProfileGenerator* generator_;
188 bool running_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100189 UnboundQueue<CodeEventsContainer> events_buffer_;
Steve Block6ded16b2010-05-10 14:33:55 +0100190 SamplingCircularQueue ticks_buffer_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100191 UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
Steve Block6ded16b2010-05-10 14:33:55 +0100192 unsigned enqueue_order_;
193};
194
195} } // namespace v8::internal
196
197
198#define PROFILE(Call) \
199 LOG(Call); \
200 do { \
201 if (v8::internal::CpuProfiler::is_profiling()) { \
202 v8::internal::CpuProfiler::Call; \
203 } \
204 } while (false)
205#else
206#define PROFILE(Call) LOG(Call)
207#endif // ENABLE_LOGGING_AND_PROFILING
208
209
210namespace v8 {
211namespace internal {
212
213class CpuProfiler {
214 public:
215 static void Setup();
216 static void TearDown();
217
218#ifdef ENABLE_LOGGING_AND_PROFILING
219 static void StartProfiling(const char* title);
220 static void StartProfiling(String* title);
221 static CpuProfile* StopProfiling(const char* title);
Leon Clarkef7060e22010-06-03 12:02:55 +0100222 static CpuProfile* StopProfiling(Object* security_token, String* title);
Steve Block6ded16b2010-05-10 14:33:55 +0100223 static int GetProfilesCount();
Leon Clarkef7060e22010-06-03 12:02:55 +0100224 static CpuProfile* GetProfile(Object* security_token, int index);
225 static CpuProfile* FindProfile(Object* security_token, unsigned uid);
Steve Block6ded16b2010-05-10 14:33:55 +0100226
227 // Invoked from stack sampler (thread or signal handler.)
228 static TickSample* TickSampleEvent();
229
230 // Must be called via PROFILE macro, otherwise will crash when
231 // profiling is not enabled.
232 static void CallbackEvent(String* name, Address entry_point);
233 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
234 Code* code, const char* comment);
235 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
236 Code* code, String* name);
237 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
238 Code* code, String* name,
239 String* source, int line);
240 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
241 Code* code, int args_count);
242 static void CodeMoveEvent(Address from, Address to);
243 static void CodeDeleteEvent(Address from);
244 static void FunctionCreateEvent(JSFunction* function);
245 static void FunctionMoveEvent(Address from, Address to);
246 static void FunctionDeleteEvent(Address from);
247 static void GetterCallbackEvent(String* name, Address entry_point);
248 static void RegExpCodeCreateEvent(Code* code, String* source);
249 static void SetterCallbackEvent(String* name, Address entry_point);
250
251 static INLINE(bool is_profiling()) {
252 return singleton_ != NULL && singleton_->processor_ != NULL;
253 }
254
255 private:
256 CpuProfiler();
257 ~CpuProfiler();
258 void StartCollectingProfile(const char* title);
259 void StartCollectingProfile(String* title);
260 void StartProcessorIfNotStarted();
261 CpuProfile* StopCollectingProfile(const char* title);
Leon Clarkef7060e22010-06-03 12:02:55 +0100262 CpuProfile* StopCollectingProfile(Object* security_token, String* title);
Steve Block6ded16b2010-05-10 14:33:55 +0100263 void StopProcessorIfLastProfile();
264
265 CpuProfilesCollection* profiles_;
266 unsigned next_profile_uid_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100267 TokenEnumerator* token_enumerator_;
Steve Block6ded16b2010-05-10 14:33:55 +0100268 ProfileGenerator* generator_;
269 ProfilerEventsProcessor* processor_;
270 int saved_logging_nesting_;
271
272 static CpuProfiler* singleton_;
273
274#else
275 static INLINE(bool is_profiling()) { return false; }
276#endif // ENABLE_LOGGING_AND_PROFILING
277
278 private:
279 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
280};
281
282} } // namespace v8::internal
283
284
285#endif // V8_CPU_PROFILER_H_