blob: d3fadb52d4a1ada74c27dfa244c245c415adea4d [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
mmassi@chromium.org49a44672012-12-04 13:52:03 +000043static const int kTickSamplesBufferChunkSize = 64 * KB;
44static const int kTickSamplesBufferChunksCount = 16;
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000045static const int kProfilerStackSize = 64 * KB;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000046
47
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +000048ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000049 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
lrn@chromium.org5d00b602011-01-05 09:51:43 +000050 generator_(generator),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000051 running_(true),
mmassi@chromium.org49a44672012-12-04 13:52:03 +000052 ticks_buffer_(sizeof(TickSampleEventRecord),
53 kTickSamplesBufferChunkSize,
ulan@chromium.org750145a2013-03-07 15:14:13 +000054 kTickSamplesBufferChunksCount),
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_);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000067 TickSample* sample = &record.sample;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +000068 sample->state = isolate->current_vm_state();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000069 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +000070 for (StackTraceFrameIterator it(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000071 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
72 it.Advance()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000073 sample->stack[sample->frames_count++] = it.frame()->pc();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000074 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000075 ticks_from_vm_buffer_.Enqueue(record);
76}
77
78
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000079void ProfilerEventsProcessor::StopSynchronously() {
80 if (!running_) return;
81 running_ = false;
82 Join();
83}
84
85
86bool ProfilerEventsProcessor::ProcessCodeEvent() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000087 CodeEventsContainer record;
88 if (events_buffer_.Dequeue(&record)) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000089 switch (record.generic.type) {
90#define PROFILER_TYPE_CASE(type, clss) \
91 case CodeEventRecord::type: \
92 record.clss##_.UpdateCodeMap(generator_->code_map()); \
93 break;
94
95 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
96
97#undef PROFILER_TYPE_CASE
98 default: return true; // Skip record.
99 }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000100 last_processed_code_event_id_ = record.generic.order;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000101 return true;
102 }
103 return false;
104}
105
106
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000107bool ProfilerEventsProcessor::ProcessTicks() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000108 while (true) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000109 if (!ticks_from_vm_buffer_.IsEmpty()
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000110 && ticks_from_vm_buffer_.Peek()->order ==
111 last_processed_code_event_id_) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000112 TickSampleEventRecord record;
113 ticks_from_vm_buffer_.Dequeue(&record);
114 generator_->RecordTickSample(record.sample);
115 }
116
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000117 const TickSampleEventRecord* rec =
118 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
119 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
120 // Make a local copy of tick sample record to ensure that it won't
121 // be modified as we are processing it. This is possible as the
122 // sampler writes w/o any sync to the queue, so if the processor
123 // will get far behind, a record may be modified right under its
124 // feet.
125 TickSampleEventRecord record = *rec;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000126 if (record.order != last_processed_code_event_id_) return true;
127
128 // A paranoid check to make sure that we don't get a memory overrun
129 // in case of frames_count having a wild value.
130 if (record.sample.frames_count < 0
131 || record.sample.frames_count > TickSample::kMaxFramesCount)
132 record.sample.frames_count = 0;
133 generator_->RecordTickSample(record.sample);
134 ticks_buffer_.FinishDequeue();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000135 }
136}
137
138
139void ProfilerEventsProcessor::Run() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000140 while (running_) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000141 // Process ticks until we have any.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000142 if (ProcessTicks()) {
143 // All ticks of the current last_processed_code_event_id_ are processed,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000144 // proceed to the next code event.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000145 ProcessCodeEvent();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000146 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000147 YieldCPU();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000148 }
149
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000150 // Process remaining tick events.
151 ticks_buffer_.FlushResidualRecords();
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000152 do {
153 ProcessTicks();
154 } while (ProcessCodeEvent());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000155}
156
157
lrn@chromium.org25156de2010-04-06 13:10:27 +0000158int CpuProfiler::GetProfilesCount() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000159 // The count of profiles doesn't depend on a security token.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000160 return profiles_->profiles()->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000161}
162
163
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000164CpuProfile* CpuProfiler::GetProfile(int index) {
165 return profiles_->profiles()->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000166}
167
168
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000169TickSample* CpuProfiler::TickSampleEvent() {
170 if (is_profiling_) return processor_->TickSampleEvent();
171 return NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000172}
173
174
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000175void CpuProfiler::DeleteAllProfiles() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000176 if (is_profiling_) StopProcessor();
177 ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000178}
179
180
181void CpuProfiler::DeleteProfile(CpuProfile* profile) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000182 profiles_->RemoveProfile(profile);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000183 delete profile;
184}
185
186
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000187static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
188 return FLAG_prof_browser_mode
189 && (tag != Logger::CALLBACK_TAG
190 && tag != Logger::FUNCTION_TAG
191 && tag != Logger::LAZY_COMPILE_TAG
192 && tag != Logger::REG_EXP_TAG
193 && tag != Logger::SCRIPT_TAG);
194}
195
196
ulan@chromium.org750145a2013-03-07 15:14:13 +0000197void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000198 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
199 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
200 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
201 rec->start = entry_point;
202 rec->entry = profiles_->NewCodeEntry(
203 Logger::CALLBACK_TAG,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000204 profiles_->GetName(name));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000205 rec->size = 1;
206 rec->shared = NULL;
207 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000208}
209
210
211void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000212 Code* code,
213 const char* name) {
214 if (FilterOutCodeCreateEvent(tag)) return;
215 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
216 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
217 rec->start = code->address();
218 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
219 rec->size = code->ExecutableSize();
220 rec->shared = NULL;
221 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000222}
223
224
225void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000226 Code* code,
227 Name* name) {
228 if (FilterOutCodeCreateEvent(tag)) return;
229 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
230 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
231 rec->start = code->address();
232 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
233 rec->size = code->ExecutableSize();
234 rec->shared = NULL;
235 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000236}
237
238
239void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000240 Code* code,
241 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000242 CompilationInfo* info,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000243 Name* name) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000244 if (FilterOutCodeCreateEvent(tag)) return;
245 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
246 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
247 rec->start = code->address();
248 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
249 if (info) {
250 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
251 }
252 if (shared->script()->IsScript()) {
253 ASSERT(Script::cast(shared->script()));
254 Script* script = Script::cast(shared->script());
255 rec->entry->set_script_id(script->id()->value());
256 }
257 rec->size = code->ExecutableSize();
258 rec->shared = shared->address();
259 processor_->Enqueue(evt_rec);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000260}
261
262
263void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
264 Code* code,
265 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000266 CompilationInfo* info,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000267 String* source, int line) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000268 if (FilterOutCodeCreateEvent(tag)) return;
269 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
270 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
271 rec->start = code->address();
272 rec->entry = profiles_->NewCodeEntry(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000273 tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000274 profiles_->GetFunctionName(shared->DebugName()),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000275 CodeEntry::kEmptyNamePrefix,
276 profiles_->GetName(source),
277 line);
278 if (info) {
279 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
280 }
281 ASSERT(Script::cast(shared->script()));
282 Script* script = Script::cast(shared->script());
283 rec->entry->set_script_id(script->id()->value());
284 rec->size = code->ExecutableSize();
285 rec->shared = shared->address();
286 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),
376 profiles_(new CpuProfilesCollection()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000377 next_profile_uid_(1),
378 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000379 processor_(NULL),
380 need_to_stop_sampler_(false),
381 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000382}
383
384
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000385CpuProfiler::CpuProfiler(Isolate* isolate,
386 CpuProfilesCollection* test_profiles,
387 ProfileGenerator* test_generator,
388 ProfilerEventsProcessor* test_processor)
389 : isolate_(isolate),
390 profiles_(test_profiles),
391 next_profile_uid_(1),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000392 generator_(test_generator),
393 processor_(test_processor),
394 need_to_stop_sampler_(false),
395 is_profiling_(false) {
396}
397
398
lrn@chromium.org25156de2010-04-06 13:10:27 +0000399CpuProfiler::~CpuProfiler() {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000400 ASSERT(!is_profiling_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000401 delete profiles_;
402}
403
404
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000405void CpuProfiler::ResetProfiles() {
406 delete profiles_;
407 profiles_ = new CpuProfilesCollection();
408}
409
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000410
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000411void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
412 if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000413 StartProcessorIfNotStarted();
414 }
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000415 processor_->AddCurrentStack(isolate_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000416}
417
418
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000419void CpuProfiler::StartProfiling(String* title, bool record_samples) {
420 StartProfiling(profiles_->GetName(title), record_samples);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000421}
422
423
424void CpuProfiler::StartProcessorIfNotStarted() {
425 if (processor_ == NULL) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000426 Logger* logger = isolate_->logger();
ager@chromium.org357bf652010-04-12 11:30:10 +0000427 // Disable logging when using the new implementation.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000428 saved_logging_nesting_ = logger->logging_nesting_;
429 logger->logging_nesting_ = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000430 generator_ = new ProfileGenerator(profiles_);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000431 processor_ = new ProfilerEventsProcessor(generator_);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000432 is_profiling_ = true;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000433 processor_->StartSynchronously();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000434 // Enumerate stuff we already have in the heap.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000435 ASSERT(isolate_->heap()->HasBeenSetUp());
436 if (!FLAG_prof_browser_mode) {
437 logger->LogCodeObjects();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000438 }
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000439 logger->LogCompiledFunctions();
440 logger->LogAccessorCallbacks();
441 LogBuiltins();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000442 // Enable stack sampling.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000443 Sampler* sampler = logger->sampler();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000444 sampler->IncreaseProfilingDepth();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000445 if (!sampler->IsActive()) {
446 sampler->Start();
447 need_to_stop_sampler_ = true;
448 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000449 }
450}
451
452
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000453CpuProfile* CpuProfiler::StopProfiling(const char* title) {
454 if (!is_profiling_) return NULL;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000455 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000456 StopProcessorIfLastProfile(title);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000457 CpuProfile* result = profiles_->StopProfiling(title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000458 if (result != NULL) {
459 result->Print();
460 }
461 return result;
462}
463
464
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000465CpuProfile* CpuProfiler::StopProfiling(String* title) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000466 if (!is_profiling_) return NULL;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000467 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000468 const char* profile_title = profiles_->GetName(title);
469 StopProcessorIfLastProfile(profile_title);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000470 return profiles_->StopProfiling(profile_title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000471}
472
473
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000474void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000475 if (profiles_->IsLastProfile(title)) StopProcessor();
476}
477
478
479void CpuProfiler::StopProcessor() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000480 Logger* logger = isolate_->logger();
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000481 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000482 sampler->DecreaseProfilingDepth();
483 if (need_to_stop_sampler_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000484 sampler->Stop();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000485 need_to_stop_sampler_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000486 }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000487 is_profiling_ = false;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000488 processor_->StopSynchronously();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000489 delete processor_;
490 delete generator_;
491 processor_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000492 generator_ = NULL;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000493 logger->logging_nesting_ = saved_logging_nesting_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000494}
495
lrn@chromium.org25156de2010-04-06 13:10:27 +0000496
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000497void CpuProfiler::LogBuiltins() {
498 Builtins* builtins = isolate_->builtins();
499 ASSERT(builtins->is_initialized());
500 for (int i = 0; i < Builtins::builtin_count; i++) {
501 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
502 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
503 Builtins::Name id = static_cast<Builtins::Name>(i);
504 rec->start = builtins->builtin(id)->address();
505 rec->builtin_id = id;
506 processor_->Enqueue(evt_rec);
507 }
508}
509
510
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000511} } // namespace v8::internal