blob: 455c89332870caa7a2a87107d77890309e951057 [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"
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000034#include "sampler.h"
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000035#include "unbound-queue.h"
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000036
37namespace v8 {
38namespace internal {
39
lrn@chromium.org25156de2010-04-06 13:10:27 +000040// Forward declarations.
41class CodeEntry;
42class CodeMap;
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000043class CompilationInfo;
lrn@chromium.org25156de2010-04-06 13:10:27 +000044class CpuProfile;
45class CpuProfilesCollection;
46class ProfileGenerator;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000047class TokenEnumerator;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000048
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000049#define CODE_EVENTS_TYPE_LIST(V) \
50 V(CODE_CREATION, CodeCreateEventRecord) \
51 V(CODE_MOVE, CodeMoveEventRecord) \
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000052 V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord)
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000053
54
55class CodeEventRecord {
56 public:
57#define DECLARE_TYPE(type, ignore) type,
58 enum Type {
59 NONE = 0,
60 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
61 NUMBER_OF_TYPES
62 };
63#undef DECLARE_TYPE
64
65 Type type;
66 unsigned order;
67};
68
69
70class CodeCreateEventRecord : public CodeEventRecord {
71 public:
72 Address start;
73 CodeEntry* entry;
74 unsigned size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000075 Address shared;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000076
lrn@chromium.org25156de2010-04-06 13:10:27 +000077 INLINE(void UpdateCodeMap(CodeMap* code_map));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000078};
79
80
81class CodeMoveEventRecord : public CodeEventRecord {
82 public:
83 Address from;
84 Address to;
85
lrn@chromium.org25156de2010-04-06 13:10:27 +000086 INLINE(void UpdateCodeMap(CodeMap* code_map));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000087};
88
89
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000090class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000091 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000092 Address from;
93 Address to;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000094
lrn@chromium.org25156de2010-04-06 13:10:27 +000095 INLINE(void UpdateCodeMap(CodeMap* code_map));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000096};
97
98
ager@chromium.org04921a82011-06-27 13:21:41 +000099class TickSampleEventRecord {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000100 public:
ager@chromium.org04921a82011-06-27 13:21:41 +0000101 // The parameterless constructor is used when we dequeue data from
102 // the ticks buffer.
103 TickSampleEventRecord() { }
104 explicit TickSampleEventRecord(unsigned order)
105 : filler(1),
106 order(order) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000107 ASSERT(filler != SamplingCircularQueue::kClear);
108 }
109
ager@chromium.org357bf652010-04-12 11:30:10 +0000110 // The first machine word of a TickSampleEventRecord must not ever
111 // become equal to SamplingCircularQueue::kClear. As both order and
112 // TickSample's first field are not reliable in this sense (order
113 // can overflow, TickSample can have all fields reset), we are
114 // forced to use an artificial filler field.
115 int filler;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000116 unsigned order;
ager@chromium.org357bf652010-04-12 11:30:10 +0000117 TickSample sample;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000118
lrn@chromium.org25156de2010-04-06 13:10:27 +0000119 static TickSampleEventRecord* cast(void* value) {
120 return reinterpret_cast<TickSampleEventRecord*>(value);
121 }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000122};
123
124
125// This class implements both the profile events processor thread and
126// methods called by event producers: VM and stack sampler threads.
127class ProfilerEventsProcessor : public Thread {
128 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000129 ProfilerEventsProcessor(ProfileGenerator* generator,
130 CpuProfilesCollection* profiles);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000131 virtual ~ProfilerEventsProcessor() {}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000132
133 // Thread control.
134 virtual void Run();
135 inline void Stop() { running_ = false; }
136 INLINE(bool running()) { return running_; }
137
138 // Events adding methods. Called by VM threads.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000139 void CallbackCreateEvent(Logger::LogEventsAndTags tag,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000140 const char* prefix, Name* name,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000141 Address start);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000142 void CodeCreateEvent(Logger::LogEventsAndTags tag,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000143 Name* name,
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000144 String* resource_name, int line_number,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000145 Address start, unsigned size,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000146 Address shared,
147 CompilationInfo* info);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000148 void CodeCreateEvent(Logger::LogEventsAndTags tag,
149 const char* name,
150 Address start, unsigned size);
151 void CodeCreateEvent(Logger::LogEventsAndTags tag,
152 int args_count,
153 Address start, unsigned size);
154 void CodeMoveEvent(Address from, Address to);
155 void CodeDeleteEvent(Address from);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000156 void SharedFunctionInfoMoveEvent(Address from, Address to);
ager@chromium.org357bf652010-04-12 11:30:10 +0000157 void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
158 const char* prefix, String* name,
159 Address start, unsigned size);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000160 // Puts current stack into tick sample events buffer.
161 void AddCurrentStack();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000162
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000163 // Tick sample events are filled directly in the buffer of the circular
164 // queue (because the structure is of fixed width, but usually not all
165 // stack frame entries are filled.) This method returns a pointer to the
166 // next record of the buffer.
167 INLINE(TickSample* TickSampleEvent());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000168
169 private:
170 union CodeEventsContainer {
171 CodeEventRecord generic;
172#define DECLARE_CLASS(ignore, type) type type##_;
173 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
174#undef DECLARE_TYPE
175 };
176
177 // Called from events processing thread (Run() method.)
178 bool ProcessCodeEvent(unsigned* dequeue_order);
179 bool ProcessTicks(unsigned dequeue_order);
180
ager@chromium.org357bf652010-04-12 11:30:10 +0000181 INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
182
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000183 ProfileGenerator* generator_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000184 CpuProfilesCollection* profiles_;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000185 bool running_;
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000186 UnboundQueue<CodeEventsContainer> events_buffer_;
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000187 SamplingCircularQueue ticks_buffer_;
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000188 UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000189 unsigned enqueue_order_;
190};
191
lrn@chromium.org25156de2010-04-06 13:10:27 +0000192
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000193#define PROFILE(IsolateGetter, Call) \
194 do { \
195 Isolate* cpu_profiler_isolate = (IsolateGetter); \
196 LOG_CODE_EVENT(cpu_profiler_isolate, Call); \
197 CpuProfiler* cpu_profiler = cpu_profiler_isolate->cpu_profiler(); \
198 if (cpu_profiler->is_profiling()) { \
199 cpu_profiler->Call; \
200 } \
lrn@chromium.org25156de2010-04-06 13:10:27 +0000201 } while (false)
lrn@chromium.org25156de2010-04-06 13:10:27 +0000202
203
lrn@chromium.org25156de2010-04-06 13:10:27 +0000204class CpuProfiler {
205 public:
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000206 explicit CpuProfiler(Isolate* isolate);
207 ~CpuProfiler();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000208
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000209 void StartProfiling(const char* title, bool record_samples = false);
210 void StartProfiling(String* title, bool record_samples);
211 CpuProfile* StopProfiling(const char* title);
212 CpuProfile* StopProfiling(Object* security_token, String* title);
213 int GetProfilesCount();
214 CpuProfile* GetProfile(Object* security_token, int index);
215 CpuProfile* FindProfile(Object* security_token, unsigned uid);
216 void DeleteAllProfiles();
217 void DeleteProfile(CpuProfile* profile);
218 bool HasDetachedProfiles();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000219
220 // Invoked from stack sampler (thread or signal handler.)
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000221 TickSample* TickSampleEvent();
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.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000225 void CallbackEvent(Name* name, Address entry_point);
226 void CodeCreateEvent(Logger::LogEventsAndTags tag,
227 Code* code, const char* comment);
228 void CodeCreateEvent(Logger::LogEventsAndTags tag,
229 Code* code, Name* name);
230 void CodeCreateEvent(Logger::LogEventsAndTags tag,
231 Code* code,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000232 SharedFunctionInfo* shared,
233 CompilationInfo* info,
234 Name* name);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000235 void CodeCreateEvent(Logger::LogEventsAndTags tag,
236 Code* code,
237 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000238 CompilationInfo* info,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000239 String* source, int line);
240 void CodeCreateEvent(Logger::LogEventsAndTags tag,
241 Code* code, int args_count);
242 void CodeMovingGCEvent() {}
243 void CodeMoveEvent(Address from, Address to);
244 void CodeDeleteEvent(Address from);
245 void GetterCallbackEvent(Name* name, Address entry_point);
246 void RegExpCodeCreateEvent(Code* code, String* source);
247 void SetterCallbackEvent(Name* name, Address entry_point);
248 void SharedFunctionInfoMoveEvent(Address from, Address to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000249
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000250 INLINE(bool is_profiling() const) { return is_profiling_; }
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000251 bool* is_profiling_address() {
252 return &is_profiling_;
253 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000254
255 private:
lrn@chromium.org25156de2010-04-06 13:10:27 +0000256 void StartProcessorIfNotStarted();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000257 void StopProcessorIfLastProfile(const char* title);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000258 void StopProcessor();
259 void ResetProfiles();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000260
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000261 Isolate* isolate_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000262 CpuProfilesCollection* profiles_;
263 unsigned next_profile_uid_;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000264 TokenEnumerator* token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000265 ProfileGenerator* generator_;
266 ProfilerEventsProcessor* processor_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000267 int saved_logging_nesting_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000268 bool need_to_stop_sampler_;
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000269 bool is_profiling_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000270
lrn@chromium.org25156de2010-04-06 13:10:27 +0000271 private:
272 DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
273};
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000274
275} } // namespace v8::internal
276
lrn@chromium.org25156de2010-04-06 13:10:27 +0000277
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000278#endif // V8_CPU_PROFILER_H_