blob: b1af621cccc1a3425e87534faafa8b14cea77c7f [file] [log] [blame]
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +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#include "v8.h"
29
30#include "cpu-profiler-inl.h"
31
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000032#include "compiler.h"
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000033#include "frames-inl.h"
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000034#include "hashmap.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000035#include "log-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "vm-state-inl.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000037
ager@chromium.org357bf652010-04-12 11:30:10 +000038#include "../include/v8-profiler.h"
39
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000040namespace v8 {
41namespace internal {
42
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000043static const int kProfilerStackSize = 64 * KB;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000044
45
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +000046ProfilerEventsProcessor::ProfilerEventsProcessor(
47 ProfileGenerator* generator,
48 Sampler* sampler,
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +000049 TimeDelta period)
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000050 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
lrn@chromium.org5d00b602011-01-05 09:51:43 +000051 generator_(generator),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +000052 sampler_(sampler),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000053 running_(true),
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +000054 period_(period),
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000055 last_code_event_id_(0), last_processed_code_event_id_(0) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000056}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000057
58
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +000059void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000060 event.generic.order = ++last_code_event_id_;
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +000061 events_buffer_.Enqueue(event);
ager@chromium.org357bf652010-04-12 11:30:10 +000062}
63
64
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000065void ProfilerEventsProcessor::AddCurrentStack(Isolate* isolate) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000066 TickSampleEventRecord record(last_code_event_id_);
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +000067 RegisterState regs;
68 StackFrameIterator it(isolate);
69 if (!it.done()) {
70 StackFrame* frame = it.frame();
71 regs.sp = frame->sp();
72 regs.fp = frame->fp();
73 regs.pc = frame->pc();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000074 }
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +000075 record.sample.Init(isolate, regs);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000076 ticks_from_vm_buffer_.Enqueue(record);
77}
78
79
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000080void ProfilerEventsProcessor::StopSynchronously() {
81 if (!running_) return;
82 running_ = false;
83 Join();
84}
85
86
87bool ProfilerEventsProcessor::ProcessCodeEvent() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000088 CodeEventsContainer record;
89 if (events_buffer_.Dequeue(&record)) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000090 switch (record.generic.type) {
91#define PROFILER_TYPE_CASE(type, clss) \
92 case CodeEventRecord::type: \
93 record.clss##_.UpdateCodeMap(generator_->code_map()); \
94 break;
95
96 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
97
98#undef PROFILER_TYPE_CASE
99 default: return true; // Skip record.
100 }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000101 last_processed_code_event_id_ = record.generic.order;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000102 return true;
103 }
104 return false;
105}
106
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000107ProfilerEventsProcessor::SampleProcessingResult
108 ProfilerEventsProcessor::ProcessOneSample() {
109 if (!ticks_from_vm_buffer_.IsEmpty()
110 && ticks_from_vm_buffer_.Peek()->order ==
111 last_processed_code_event_id_) {
112 TickSampleEventRecord record;
113 ticks_from_vm_buffer_.Dequeue(&record);
114 generator_->RecordTickSample(record.sample);
115 return OneSampleProcessed;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000116 }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000117
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000118 const TickSampleEventRecord* record = ticks_buffer_.Peek();
119 if (record == NULL) {
120 if (ticks_from_vm_buffer_.IsEmpty()) return NoSamplesInQueue;
121 return FoundSampleForNextCodeEvent;
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000122 }
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000123 if (record->order != last_processed_code_event_id_) {
124 return FoundSampleForNextCodeEvent;
125 }
126 generator_->RecordTickSample(record->sample);
127 ticks_buffer_.Remove();
128 return OneSampleProcessed;
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000129}
130
131
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000132void ProfilerEventsProcessor::Run() {
133 while (running_) {
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000134 ElapsedTimer timer;
135 timer.Start();
136 // Keep processing existing events until we need to do next sample.
137 do {
138 if (FoundSampleForNextCodeEvent == ProcessOneSample()) {
139 // All ticks of the current last_processed_code_event_id_ are
140 // processed, proceed to the next code event.
141 ProcessCodeEvent();
142 }
143 } while (!timer.HasExpired(period_));
144
145 // Schedule next sample. sampler_ is NULL in tests.
146 if (sampler_) sampler_->DoSample();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000147 }
148
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000149 // Process remaining tick events.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000150 do {
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000151 SampleProcessingResult result;
152 do {
153 result = ProcessOneSample();
154 } while (result == OneSampleProcessed);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000155 } while (ProcessCodeEvent());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000156}
157
158
lrn@chromium.org25156de2010-04-06 13:10:27 +0000159int CpuProfiler::GetProfilesCount() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000160 // The count of profiles doesn't depend on a security token.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000161 return profiles_->profiles()->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000162}
163
164
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000165CpuProfile* CpuProfiler::GetProfile(int index) {
166 return profiles_->profiles()->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000167}
168
169
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000170void CpuProfiler::DeleteAllProfiles() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000171 if (is_profiling_) StopProcessor();
172 ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000173}
174
175
176void CpuProfiler::DeleteProfile(CpuProfile* profile) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000177 profiles_->RemoveProfile(profile);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000178 delete profile;
179}
180
181
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000182static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
183 return FLAG_prof_browser_mode
184 && (tag != Logger::CALLBACK_TAG
185 && tag != Logger::FUNCTION_TAG
186 && tag != Logger::LAZY_COMPILE_TAG
187 && tag != Logger::REG_EXP_TAG
188 && tag != Logger::SCRIPT_TAG);
189}
190
191
ulan@chromium.org750145a2013-03-07 15:14:13 +0000192void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000193 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
194 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
195 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
196 rec->start = entry_point;
197 rec->entry = profiles_->NewCodeEntry(
198 Logger::CALLBACK_TAG,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000199 profiles_->GetName(name));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000200 rec->size = 1;
201 rec->shared = NULL;
202 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000203}
204
205
206void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000207 Code* code,
208 const char* name) {
209 if (FilterOutCodeCreateEvent(tag)) return;
210 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
211 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
212 rec->start = code->address();
213 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
214 rec->size = code->ExecutableSize();
215 rec->shared = NULL;
216 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000217}
218
219
220void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000221 Code* code,
222 Name* name) {
223 if (FilterOutCodeCreateEvent(tag)) return;
224 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
225 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
226 rec->start = code->address();
227 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
228 rec->size = code->ExecutableSize();
229 rec->shared = NULL;
230 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000231}
232
233
234void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000235 Code* code,
236 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000237 CompilationInfo* info,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000238 Name* name) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000239 if (FilterOutCodeCreateEvent(tag)) return;
240 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
241 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
242 rec->start = code->address();
243 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
244 if (info) {
245 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
246 }
247 if (shared->script()->IsScript()) {
248 ASSERT(Script::cast(shared->script()));
249 Script* script = Script::cast(shared->script());
250 rec->entry->set_script_id(script->id()->value());
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000251 rec->entry->set_bailout_reason(
252 GetBailoutReason(shared->DisableOptimizationReason()));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000253 }
254 rec->size = code->ExecutableSize();
255 rec->shared = shared->address();
256 processor_->Enqueue(evt_rec);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000257}
258
259
260void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
261 Code* code,
262 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000263 CompilationInfo* info,
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000264 Name* source, int line, int column) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000265 if (FilterOutCodeCreateEvent(tag)) return;
266 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
267 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
268 rec->start = code->address();
269 rec->entry = profiles_->NewCodeEntry(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000270 tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000271 profiles_->GetFunctionName(shared->DebugName()),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000272 CodeEntry::kEmptyNamePrefix,
273 profiles_->GetName(source),
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000274 line,
275 column);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000276 if (info) {
277 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
278 }
279 ASSERT(Script::cast(shared->script()));
280 Script* script = Script::cast(shared->script());
281 rec->entry->set_script_id(script->id()->value());
282 rec->size = code->ExecutableSize();
283 rec->shared = shared->address();
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000284 rec->entry->set_bailout_reason(
285 GetBailoutReason(shared->DisableOptimizationReason()));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000286 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000287}
288
289
290void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000291 Code* code,
292 int args_count) {
293 if (FilterOutCodeCreateEvent(tag)) return;
294 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
295 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
296 rec->start = code->address();
297 rec->entry = profiles_->NewCodeEntry(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000298 tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000299 profiles_->GetName(args_count),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000300 "args_count: ");
301 rec->size = code->ExecutableSize();
302 rec->shared = NULL;
303 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000304}
305
306
307void CpuProfiler::CodeMoveEvent(Address from, Address to) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000308 CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
309 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
310 rec->from = from;
311 rec->to = to;
312 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000313}
314
315
316void CpuProfiler::CodeDeleteEvent(Address from) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000317}
318
319
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000320void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000321 CodeEventsContainer evt_rec(CodeEventRecord::SHARED_FUNC_MOVE);
322 SharedFunctionInfoMoveEventRecord* rec =
323 &evt_rec.SharedFunctionInfoMoveEventRecord_;
324 rec->from = from;
325 rec->to = to;
326 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000327}
328
329
ulan@chromium.org750145a2013-03-07 15:14:13 +0000330void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000331 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
332 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
333 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
334 rec->start = entry_point;
335 rec->entry = profiles_->NewCodeEntry(
336 Logger::CALLBACK_TAG,
337 profiles_->GetName(name),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000338 "get ");
339 rec->size = 1;
340 rec->shared = NULL;
341 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000342}
343
344
345void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000346 if (FilterOutCodeCreateEvent(Logger::REG_EXP_TAG)) return;
347 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
348 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
349 rec->start = code->address();
350 rec->entry = profiles_->NewCodeEntry(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000351 Logger::REG_EXP_TAG,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000352 profiles_->GetName(source),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000353 "RegExp: ");
354 rec->size = code->ExecutableSize();
355 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000356}
357
358
ulan@chromium.org750145a2013-03-07 15:14:13 +0000359void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000360 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
361 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
362 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
363 rec->start = entry_point;
364 rec->entry = profiles_->NewCodeEntry(
365 Logger::CALLBACK_TAG,
366 profiles_->GetName(name),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000367 "set ");
368 rec->size = 1;
369 rec->shared = NULL;
370 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000371}
372
373
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000374CpuProfiler::CpuProfiler(Isolate* isolate)
375 : isolate_(isolate),
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000376 sampling_interval_(TimeDelta::FromMicroseconds(
377 FLAG_cpu_profiler_sampling_interval)),
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000378 profiles_(new CpuProfilesCollection(isolate->heap())),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000379 next_profile_uid_(1),
380 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000381 processor_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000382 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000383}
384
385
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000386CpuProfiler::CpuProfiler(Isolate* isolate,
387 CpuProfilesCollection* test_profiles,
388 ProfileGenerator* test_generator,
389 ProfilerEventsProcessor* test_processor)
390 : isolate_(isolate),
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000391 sampling_interval_(TimeDelta::FromMicroseconds(
392 FLAG_cpu_profiler_sampling_interval)),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000393 profiles_(test_profiles),
394 next_profile_uid_(1),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000395 generator_(test_generator),
396 processor_(test_processor),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000397 is_profiling_(false) {
398}
399
400
lrn@chromium.org25156de2010-04-06 13:10:27 +0000401CpuProfiler::~CpuProfiler() {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000402 ASSERT(!is_profiling_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000403 delete profiles_;
404}
405
406
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000407void CpuProfiler::set_sampling_interval(TimeDelta value) {
408 ASSERT(!is_profiling_);
409 sampling_interval_ = value;
410}
411
412
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000413void CpuProfiler::ResetProfiles() {
414 delete profiles_;
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000415 profiles_ = new CpuProfilesCollection(isolate()->heap());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000416}
417
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000418
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000419void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
420 if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000421 StartProcessorIfNotStarted();
422 }
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000423 processor_->AddCurrentStack(isolate_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000424}
425
426
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000427void CpuProfiler::StartProfiling(String* title, bool record_samples) {
428 StartProfiling(profiles_->GetName(title), record_samples);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000429}
430
431
432void CpuProfiler::StartProcessorIfNotStarted() {
433 if (processor_ == NULL) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000434 Logger* logger = isolate_->logger();
ager@chromium.org357bf652010-04-12 11:30:10 +0000435 // Disable logging when using the new implementation.
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000436 saved_is_logging_ = logger->is_logging_;
437 logger->is_logging_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000438 generator_ = new ProfileGenerator(profiles_);
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000439 Sampler* sampler = logger->sampler();
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000440#if V8_CC_MSVC && (_MSC_VER >= 1800)
441 // VS2013 reports "warning C4316: 'v8::internal::ProfilerEventsProcessor'
442 // : object allocated on the heap may not be aligned 64". We need to
443 // figure out if this is a legitimate warning or a compiler bug.
444 #pragma warning(push)
445 #pragma warning(disable:4316)
446#endif
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000447 processor_ = new ProfilerEventsProcessor(
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000448 generator_, sampler, sampling_interval_);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000449#if V8_CC_MSVC && (_MSC_VER >= 1800)
450 #pragma warning(pop)
451#endif
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000452 is_profiling_ = true;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000453 // Enumerate stuff we already have in the heap.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000454 ASSERT(isolate_->heap()->HasBeenSetUp());
455 if (!FLAG_prof_browser_mode) {
456 logger->LogCodeObjects();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000457 }
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000458 logger->LogCompiledFunctions();
459 logger->LogAccessorCallbacks();
460 LogBuiltins();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000461 // Enable stack sampling.
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000462 sampler->SetHasProcessingThread(true);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000463 sampler->IncreaseProfilingDepth();
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000464 processor_->StartSynchronously();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000465 }
466}
467
468
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000469CpuProfile* CpuProfiler::StopProfiling(const char* title) {
470 if (!is_profiling_) return NULL;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000471 StopProcessorIfLastProfile(title);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000472 CpuProfile* result = profiles_->StopProfiling(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000473 if (result != NULL) {
474 result->Print();
475 }
476 return result;
477}
478
479
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000480CpuProfile* CpuProfiler::StopProfiling(String* title) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000481 if (!is_profiling_) return NULL;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000482 const char* profile_title = profiles_->GetName(title);
483 StopProcessorIfLastProfile(profile_title);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000484 return profiles_->StopProfiling(profile_title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000485}
486
487
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000488void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000489 if (profiles_->IsLastProfile(title)) StopProcessor();
490}
491
492
493void CpuProfiler::StopProcessor() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000494 Logger* logger = isolate_->logger();
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000495 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000496 is_profiling_ = false;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000497 processor_->StopSynchronously();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000498 delete processor_;
499 delete generator_;
500 processor_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000501 generator_ = NULL;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000502 sampler->SetHasProcessingThread(false);
503 sampler->DecreaseProfilingDepth();
504 logger->is_logging_ = saved_is_logging_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000505}
506
lrn@chromium.org25156de2010-04-06 13:10:27 +0000507
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000508void CpuProfiler::LogBuiltins() {
509 Builtins* builtins = isolate_->builtins();
510 ASSERT(builtins->is_initialized());
511 for (int i = 0; i < Builtins::builtin_count; i++) {
512 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
513 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
514 Builtins::Name id = static_cast<Builtins::Name>(i);
515 rec->start = builtins->builtin(id)->address();
516 rec->builtin_id = id;
517 processor_->Enqueue(evt_rec);
518 }
519}
520
521
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000522} } // namespace v8::internal