blob: 6e2e771a41fbfa3c8e59d3066d02cbb559896a1e [file] [log] [blame]
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +00001// Copyright 2012 the V8 project authors. All rights reserved.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00002// 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
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000032#include "atomicops.h"
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000033#include "circular-queue.h"
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000034#include "unbound-queue.h"
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000035
36namespace v8 {
37namespace internal {
38
lrn@chromium.org25156de2010-04-06 13:10:27 +000039// Forward declarations.
40class CodeEntry;
41class CodeMap;
42class CpuProfile;
43class CpuProfilesCollection;
44class ProfileGenerator;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000045class TokenEnumerator;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000046
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000047#define CODE_EVENTS_TYPE_LIST(V) \
48 V(CODE_CREATION, CodeCreateEventRecord) \
49 V(CODE_MOVE, CodeMoveEventRecord) \
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000050 V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord)
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000051
52
53class CodeEventRecord {
54 public:
55#define DECLARE_TYPE(type, ignore) type,
56 enum Type {
57 NONE = 0,
58 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
59 NUMBER_OF_TYPES
60 };
61#undef DECLARE_TYPE
62
63 Type type;
64 unsigned order;
65};
66
67
68class CodeCreateEventRecord : public CodeEventRecord {
69 public:
70 Address start;
71 CodeEntry* entry;
72 unsigned size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000073 Address shared;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000074
lrn@chromium.org25156de2010-04-06 13:10:27 +000075 INLINE(void UpdateCodeMap(CodeMap* code_map));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000076};
77
78
79class CodeMoveEventRecord : public CodeEventRecord {
80 public:
81 Address from;
82 Address to;
83
lrn@chromium.org25156de2010-04-06 13:10:27 +000084 INLINE(void UpdateCodeMap(CodeMap* code_map));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000085};
86
87
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000088class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000089 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000090 Address from;
91 Address to;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000092
lrn@chromium.org25156de2010-04-06 13:10:27 +000093 INLINE(void UpdateCodeMap(CodeMap* code_map));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000094};
95
96
ager@chromium.org04921a82011-06-27 13:21:41 +000097class TickSampleEventRecord {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000098 public:
ager@chromium.org04921a82011-06-27 13:21:41 +000099 // The parameterless constructor is used when we dequeue data from
100 // the ticks buffer.
101 TickSampleEventRecord() { }
102 explicit TickSampleEventRecord(unsigned order)
103 : filler(1),
104 order(order) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000105 ASSERT(filler != SamplingCircularQueue::kClear);
106 }
107
ager@chromium.org357bf652010-04-12 11:30:10 +0000108 // The first machine word of a TickSampleEventRecord must not ever
109 // become equal to SamplingCircularQueue::kClear. As both order and
110 // TickSample's first field are not reliable in this sense (order
111 // can overflow, TickSample can have all fields reset), we are
112 // forced to use an artificial filler field.
113 int filler;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000114 unsigned order;
ager@chromium.org357bf652010-04-12 11:30:10 +0000115 TickSample sample;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000116
lrn@chromium.org25156de2010-04-06 13:10:27 +0000117 static TickSampleEventRecord* cast(void* value) {
118 return reinterpret_cast<TickSampleEventRecord*>(value);
119 }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000120};
121
122
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 Thread {
126 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000127 explicit ProfilerEventsProcessor(ProfileGenerator* generator);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000128 virtual ~ProfilerEventsProcessor() {}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000129
130 // Thread control.
131 virtual void Run();
132 inline void Stop() { running_ = false; }
133 INLINE(bool running()) { return running_; }
134
135 // Events adding methods. Called by VM threads.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000136 void CallbackCreateEvent(Logger::LogEventsAndTags tag,
137 const char* prefix, String* name,
138 Address start);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000139 void CodeCreateEvent(Logger::LogEventsAndTags tag,
140 String* name,
141 String* resource_name, int line_number,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000142 Address start, unsigned size,
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000143 Address shared);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000144 void CodeCreateEvent(Logger::LogEventsAndTags tag,
145 const char* name,
146 Address start, unsigned size);
147 void CodeCreateEvent(Logger::LogEventsAndTags tag,
148 int args_count,
149 Address start, unsigned size);
150 void CodeMoveEvent(Address from, Address to);
151 void CodeDeleteEvent(Address from);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000152 void SharedFunctionInfoMoveEvent(Address from, Address to);
ager@chromium.org357bf652010-04-12 11:30:10 +0000153 void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
154 const char* prefix, String* name,
155 Address start, unsigned size);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000156 // Puts current stack into tick sample events buffer.
157 void AddCurrentStack();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000158
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000159 // Tick sample events are filled directly in the buffer of the circular
160 // queue (because the structure is of fixed width, but usually not all
161 // stack frame entries are filled.) This method returns a pointer to the
162 // next record of the buffer.
163 INLINE(TickSample* TickSampleEvent());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000164
165 private:
166 union CodeEventsContainer {
167 CodeEventRecord generic;
168#define DECLARE_CLASS(ignore, type) type type##_;
169 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
170#undef DECLARE_TYPE
171 };
172
173 // Called from events processing thread (Run() method.)
174 bool ProcessCodeEvent(unsigned* dequeue_order);
175 bool ProcessTicks(unsigned dequeue_order);
176
ager@chromium.org357bf652010-04-12 11:30:10 +0000177 INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
178
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000179 ProfileGenerator* generator_;
180 bool running_;
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000181 UnboundQueue<CodeEventsContainer> events_buffer_;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000182 SamplingCircularQueue ticks_buffer_;
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000183 UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000184 unsigned enqueue_order_;
185};
186
lrn@chromium.org25156de2010-04-06 13:10:27 +0000187} } // namespace v8::internal
188
189
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000190#define PROFILE(isolate, Call) \
191 LOG(isolate, Call); \
192 do { \
193 if (v8::internal::CpuProfiler::is_profiling(isolate)) { \
194 v8::internal::CpuProfiler::Call; \
195 } \
lrn@chromium.org25156de2010-04-06 13:10:27 +0000196 } while (false)
lrn@chromium.org25156de2010-04-06 13:10:27 +0000197
198
199namespace v8 {
200namespace internal {
201
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000202
203// TODO(isolates): isolatify this class.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000204class CpuProfiler {
205 public:
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000206 static void SetUp();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000207 static void TearDown();
208
lrn@chromium.org25156de2010-04-06 13:10:27 +0000209 static void StartProfiling(const char* title);
210 static void StartProfiling(String* title);
211 static CpuProfile* StopProfiling(const char* title);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000212 static CpuProfile* StopProfiling(Object* security_token, String* title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000213 static int GetProfilesCount();
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000214 static CpuProfile* GetProfile(Object* security_token, int index);
215 static CpuProfile* FindProfile(Object* security_token, unsigned uid);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000216 static void DeleteAllProfiles();
217 static void DeleteProfile(CpuProfile* profile);
218 static bool HasDetachedProfiles();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000219
220 // Invoked from stack sampler (thread or signal handler.)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000221 static TickSample* TickSampleEvent(Isolate* isolate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000222
223 // Must be called via PROFILE macro, otherwise will crash when
224 // profiling is not enabled.
225 static void CallbackEvent(String* name, Address entry_point);
226 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
227 Code* code, const char* comment);
228 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
229 Code* code, String* name);
230 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000231 Code* code,
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000232 SharedFunctionInfo* shared,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000233 String* name);
234 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
235 Code* code,
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000236 SharedFunctionInfo* shared,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000237 String* source, int line);
238 static void CodeCreateEvent(Logger::LogEventsAndTags tag,
239 Code* code, int args_count);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000240 static void CodeMovingGCEvent() {}
lrn@chromium.org25156de2010-04-06 13:10:27 +0000241 static void CodeMoveEvent(Address from, Address to);
242 static void CodeDeleteEvent(Address from);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000243 static void GetterCallbackEvent(String* name, Address entry_point);
244 static void RegExpCodeCreateEvent(Code* code, String* source);
245 static void SetterCallbackEvent(String* name, Address entry_point);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000246 static void SharedFunctionInfoMoveEvent(Address from, Address to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000247
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000248 // TODO(isolates): this doesn't have to use atomics anymore.
249
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000250 static INLINE(bool is_profiling(Isolate* isolate)) {
251 CpuProfiler* profiler = isolate->cpu_profiler();
252 return profiler != NULL && NoBarrier_Load(&profiler->is_profiling_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000253 }
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);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000262 CpuProfile* StopCollectingProfile(Object* security_token, String* title);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000263 void StopProcessorIfLastProfile(const char* title);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000264 void StopProcessor();
265 void ResetProfiles();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000266
267 CpuProfilesCollection* profiles_;
268 unsigned next_profile_uid_;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000269 TokenEnumerator* token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000270 ProfileGenerator* generator_;
271 ProfilerEventsProcessor* processor_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000272 int saved_logging_nesting_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000273 bool need_to_stop_sampler_;
274 Atomic32 is_profiling_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000275
lrn@chromium.org25156de2010-04-06 13:10:27 +0000276 private:
277 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
278};
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000279
280} } // namespace v8::internal
281
lrn@chromium.org25156de2010-04-06 13:10:27 +0000282
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000283#endif // V8_CPU_PROFILER_H_