blob: 34bebb8eca1bfe8cd220240ff297fa972d8430f4 [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_);
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) {
danno@chromium.org59400602013-08-13 17:09:37 +0000109 while (!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
rossberg@chromium.org92597162013-08-23 13:28:00 +0000117 const TickSampleEventRecord* record = ticks_buffer_.StartDequeue();
118 if (record == NULL) return !ticks_from_vm_buffer_.IsEmpty();
119 if (record->order != last_processed_code_event_id_) return true;
120 generator_->RecordTickSample(record->sample);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000121 ticks_buffer_.FinishDequeue();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000122 }
123}
124
125
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000126void ProfilerEventsProcessor::ProcessEventsAndDoSample() {
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000127 ElapsedTimer timer;
128 timer.Start();
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000129 // Keep processing existing events until we need to do next sample.
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000130 while (!timer.HasExpired(period_)) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000131 if (ProcessTicks()) {
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000132 // All ticks of the current dequeue_order are processed,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000133 // proceed to the next code event.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000134 ProcessCodeEvent();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000135 }
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000136 }
137 // Schedule next sample. sampler_ is NULL in tests.
138 if (sampler_) sampler_->DoSample();
139}
140
141
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000142void ProfilerEventsProcessor::Run() {
143 while (running_) {
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000144 ProcessEventsAndDoSample();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000145 }
146
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000147 // Process remaining tick events.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000148 do {
149 ProcessTicks();
150 } while (ProcessCodeEvent());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000151}
152
153
lrn@chromium.org25156de2010-04-06 13:10:27 +0000154int CpuProfiler::GetProfilesCount() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000155 // The count of profiles doesn't depend on a security token.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000156 return profiles_->profiles()->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000157}
158
159
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000160CpuProfile* CpuProfiler::GetProfile(int index) {
161 return profiles_->profiles()->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000162}
163
164
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000165void CpuProfiler::DeleteAllProfiles() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000166 if (is_profiling_) StopProcessor();
167 ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000168}
169
170
171void CpuProfiler::DeleteProfile(CpuProfile* profile) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000172 profiles_->RemoveProfile(profile);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000173 delete profile;
174}
175
176
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000177static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
178 return FLAG_prof_browser_mode
179 && (tag != Logger::CALLBACK_TAG
180 && tag != Logger::FUNCTION_TAG
181 && tag != Logger::LAZY_COMPILE_TAG
182 && tag != Logger::REG_EXP_TAG
183 && tag != Logger::SCRIPT_TAG);
184}
185
186
ulan@chromium.org750145a2013-03-07 15:14:13 +0000187void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000188 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
189 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
190 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
191 rec->start = entry_point;
192 rec->entry = profiles_->NewCodeEntry(
193 Logger::CALLBACK_TAG,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000194 profiles_->GetName(name));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000195 rec->size = 1;
196 rec->shared = NULL;
197 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000198}
199
200
201void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000202 Code* code,
203 const char* name) {
204 if (FilterOutCodeCreateEvent(tag)) return;
205 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
206 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
207 rec->start = code->address();
208 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
209 rec->size = code->ExecutableSize();
210 rec->shared = NULL;
211 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000212}
213
214
215void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000216 Code* code,
217 Name* name) {
218 if (FilterOutCodeCreateEvent(tag)) return;
219 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
220 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
221 rec->start = code->address();
222 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
223 rec->size = code->ExecutableSize();
224 rec->shared = NULL;
225 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000226}
227
228
229void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000230 Code* code,
231 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000232 CompilationInfo* info,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000233 Name* name) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000234 if (FilterOutCodeCreateEvent(tag)) return;
235 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
236 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
237 rec->start = code->address();
238 rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
239 if (info) {
240 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
241 }
242 if (shared->script()->IsScript()) {
243 ASSERT(Script::cast(shared->script()));
244 Script* script = Script::cast(shared->script());
245 rec->entry->set_script_id(script->id()->value());
246 }
247 rec->size = code->ExecutableSize();
248 rec->shared = shared->address();
249 processor_->Enqueue(evt_rec);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000250}
251
252
253void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
254 Code* code,
255 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000256 CompilationInfo* info,
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000257 Name* source, int line) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000258 if (FilterOutCodeCreateEvent(tag)) return;
259 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
260 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
261 rec->start = code->address();
262 rec->entry = profiles_->NewCodeEntry(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000263 tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000264 profiles_->GetFunctionName(shared->DebugName()),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000265 CodeEntry::kEmptyNamePrefix,
266 profiles_->GetName(source),
267 line);
268 if (info) {
269 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
270 }
271 ASSERT(Script::cast(shared->script()));
272 Script* script = Script::cast(shared->script());
273 rec->entry->set_script_id(script->id()->value());
274 rec->size = code->ExecutableSize();
275 rec->shared = shared->address();
276 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000277}
278
279
280void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000281 Code* code,
282 int args_count) {
283 if (FilterOutCodeCreateEvent(tag)) return;
284 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
285 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
286 rec->start = code->address();
287 rec->entry = profiles_->NewCodeEntry(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000288 tag,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000289 profiles_->GetName(args_count),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000290 "args_count: ");
291 rec->size = code->ExecutableSize();
292 rec->shared = NULL;
293 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000294}
295
296
297void CpuProfiler::CodeMoveEvent(Address from, Address to) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000298 CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
299 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
300 rec->from = from;
301 rec->to = to;
302 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000303}
304
305
306void CpuProfiler::CodeDeleteEvent(Address from) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000307}
308
309
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000310void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000311 CodeEventsContainer evt_rec(CodeEventRecord::SHARED_FUNC_MOVE);
312 SharedFunctionInfoMoveEventRecord* rec =
313 &evt_rec.SharedFunctionInfoMoveEventRecord_;
314 rec->from = from;
315 rec->to = to;
316 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000317}
318
319
ulan@chromium.org750145a2013-03-07 15:14:13 +0000320void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000321 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
322 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
323 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
324 rec->start = entry_point;
325 rec->entry = profiles_->NewCodeEntry(
326 Logger::CALLBACK_TAG,
327 profiles_->GetName(name),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000328 "get ");
329 rec->size = 1;
330 rec->shared = NULL;
331 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000332}
333
334
335void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000336 if (FilterOutCodeCreateEvent(Logger::REG_EXP_TAG)) return;
337 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
338 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
339 rec->start = code->address();
340 rec->entry = profiles_->NewCodeEntry(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000341 Logger::REG_EXP_TAG,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000342 profiles_->GetName(source),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000343 "RegExp: ");
344 rec->size = code->ExecutableSize();
345 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000346}
347
348
ulan@chromium.org750145a2013-03-07 15:14:13 +0000349void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000350 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
351 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
352 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
353 rec->start = entry_point;
354 rec->entry = profiles_->NewCodeEntry(
355 Logger::CALLBACK_TAG,
356 profiles_->GetName(name),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000357 "set ");
358 rec->size = 1;
359 rec->shared = NULL;
360 processor_->Enqueue(evt_rec);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000361}
362
363
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000364CpuProfiler::CpuProfiler(Isolate* isolate)
365 : isolate_(isolate),
366 profiles_(new CpuProfilesCollection()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000367 next_profile_uid_(1),
368 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000369 processor_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000370 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000371}
372
373
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000374CpuProfiler::CpuProfiler(Isolate* isolate,
375 CpuProfilesCollection* test_profiles,
376 ProfileGenerator* test_generator,
377 ProfilerEventsProcessor* test_processor)
378 : isolate_(isolate),
379 profiles_(test_profiles),
380 next_profile_uid_(1),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000381 generator_(test_generator),
382 processor_(test_processor),
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000383 is_profiling_(false) {
384}
385
386
lrn@chromium.org25156de2010-04-06 13:10:27 +0000387CpuProfiler::~CpuProfiler() {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000388 ASSERT(!is_profiling_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000389 delete profiles_;
390}
391
392
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000393void CpuProfiler::ResetProfiles() {
394 delete profiles_;
395 profiles_ = new CpuProfilesCollection();
396}
397
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000398
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000399void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
400 if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000401 StartProcessorIfNotStarted();
402 }
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000403 processor_->AddCurrentStack(isolate_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000404}
405
406
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000407void CpuProfiler::StartProfiling(String* title, bool record_samples) {
408 StartProfiling(profiles_->GetName(title), record_samples);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000409}
410
411
412void CpuProfiler::StartProcessorIfNotStarted() {
413 if (processor_ == NULL) {
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000414 Logger* logger = isolate_->logger();
ager@chromium.org357bf652010-04-12 11:30:10 +0000415 // Disable logging when using the new implementation.
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000416 saved_is_logging_ = logger->is_logging_;
417 logger->is_logging_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000418 generator_ = new ProfileGenerator(profiles_);
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000419 Sampler* sampler = logger->sampler();
420 processor_ = new ProfilerEventsProcessor(
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000421 generator_, sampler,
422 TimeDelta::FromMicroseconds(FLAG_cpu_profiler_sampling_interval));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000423 is_profiling_ = true;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000424 // Enumerate stuff we already have in the heap.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000425 ASSERT(isolate_->heap()->HasBeenSetUp());
426 if (!FLAG_prof_browser_mode) {
427 logger->LogCodeObjects();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000428 }
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000429 logger->LogCompiledFunctions();
430 logger->LogAccessorCallbacks();
431 LogBuiltins();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000432 // Enable stack sampling.
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000433 sampler->SetHasProcessingThread(true);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000434 sampler->IncreaseProfilingDepth();
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000435 processor_->StartSynchronously();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000436 }
437}
438
439
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000440CpuProfile* CpuProfiler::StopProfiling(const char* title) {
441 if (!is_profiling_) return NULL;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000442 StopProcessorIfLastProfile(title);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000443 CpuProfile* result = profiles_->StopProfiling(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000444 if (result != NULL) {
445 result->Print();
446 }
447 return result;
448}
449
450
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000451CpuProfile* CpuProfiler::StopProfiling(String* title) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000452 if (!is_profiling_) return NULL;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000453 const char* profile_title = profiles_->GetName(title);
454 StopProcessorIfLastProfile(profile_title);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000455 return profiles_->StopProfiling(profile_title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000456}
457
458
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000459void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000460 if (profiles_->IsLastProfile(title)) StopProcessor();
461}
462
463
464void CpuProfiler::StopProcessor() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000465 Logger* logger = isolate_->logger();
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000466 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000467 is_profiling_ = false;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000468 processor_->StopSynchronously();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000469 delete processor_;
470 delete generator_;
471 processor_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000472 generator_ = NULL;
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000473 sampler->SetHasProcessingThread(false);
474 sampler->DecreaseProfilingDepth();
475 logger->is_logging_ = saved_is_logging_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000476}
477
lrn@chromium.org25156de2010-04-06 13:10:27 +0000478
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000479void CpuProfiler::LogBuiltins() {
480 Builtins* builtins = isolate_->builtins();
481 ASSERT(builtins->is_initialized());
482 for (int i = 0; i < Builtins::builtin_count; i++) {
483 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
484 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
485 Builtins::Name id = static_cast<Builtins::Name>(i);
486 rec->start = builtins->builtin(id)->address();
487 rec->builtin_id = id;
488 processor_->Enqueue(evt_rec);
489 }
490}
491
492
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000493} } // namespace v8::internal