blob: 4248a64338f81228fbfdb9eb0fb41fa097748c5a [file] [log] [blame]
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001// Copyright 2010 the V8 project authors. All rights reserved.
2// 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
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000032#ifdef ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +000033
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000034#include "frames-inl.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000035#include "log-inl.h"
36
ager@chromium.org357bf652010-04-12 11:30:10 +000037#include "../include/v8-profiler.h"
38
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000039namespace v8 {
40namespace internal {
41
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000042static const int kEventsBufferSize = 256*KB;
43static const int kTickSamplesBufferChunkSize = 64*KB;
44static const int kTickSamplesBufferChunksCount = 16;
45
46
47ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
48 : generator_(generator),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000049 running_(true),
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000050 ticks_buffer_(sizeof(TickSampleEventRecord),
51 kTickSamplesBufferChunkSize,
52 kTickSamplesBufferChunksCount),
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000053 enqueue_order_(0) {
54}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000055
56
lrn@chromium.org25156de2010-04-06 13:10:27 +000057void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
58 const char* prefix,
59 String* name,
60 Address start) {
ager@chromium.org357bf652010-04-12 11:30:10 +000061 if (FilterOutCodeCreateEvent(tag)) return;
lrn@chromium.org25156de2010-04-06 13:10:27 +000062 CodeEventsContainer evt_rec;
63 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
64 rec->type = CodeEventRecord::CODE_CREATION;
65 rec->order = ++enqueue_order_;
66 rec->start = start;
67 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
68 rec->size = 1;
69 events_buffer_.Enqueue(evt_rec);
70}
71
72
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000073void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
74 String* name,
75 String* resource_name,
76 int line_number,
77 Address start,
78 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +000079 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000080 CodeEventsContainer evt_rec;
81 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
82 rec->type = CodeEventRecord::CODE_CREATION;
83 rec->order = ++enqueue_order_;
84 rec->start = start;
85 rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
86 rec->size = size;
87 events_buffer_.Enqueue(evt_rec);
88}
89
90
91void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
92 const char* name,
93 Address start,
94 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +000095 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000096 CodeEventsContainer evt_rec;
97 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
98 rec->type = CodeEventRecord::CODE_CREATION;
99 rec->order = ++enqueue_order_;
100 rec->start = start;
101 rec->entry = generator_->NewCodeEntry(tag, name);
102 rec->size = size;
103 events_buffer_.Enqueue(evt_rec);
104}
105
106
107void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
108 int args_count,
109 Address start,
110 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000111 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000112 CodeEventsContainer evt_rec;
113 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
114 rec->type = CodeEventRecord::CODE_CREATION;
115 rec->order = ++enqueue_order_;
116 rec->start = start;
117 rec->entry = generator_->NewCodeEntry(tag, args_count);
118 rec->size = size;
119 events_buffer_.Enqueue(evt_rec);
120}
121
122
123void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
124 CodeEventsContainer evt_rec;
125 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
126 rec->type = CodeEventRecord::CODE_MOVE;
127 rec->order = ++enqueue_order_;
128 rec->from = from;
129 rec->to = to;
130 events_buffer_.Enqueue(evt_rec);
131}
132
133
134void ProfilerEventsProcessor::CodeDeleteEvent(Address from) {
135 CodeEventsContainer evt_rec;
136 CodeDeleteEventRecord* rec = &evt_rec.CodeDeleteEventRecord_;
137 rec->type = CodeEventRecord::CODE_DELETE;
138 rec->order = ++enqueue_order_;
139 rec->start = from;
140 events_buffer_.Enqueue(evt_rec);
141}
142
143
144void ProfilerEventsProcessor::FunctionCreateEvent(Address alias,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000145 Address start,
146 int security_token_id) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000147 CodeEventsContainer evt_rec;
148 CodeAliasEventRecord* rec = &evt_rec.CodeAliasEventRecord_;
149 rec->type = CodeEventRecord::CODE_ALIAS;
150 rec->order = ++enqueue_order_;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000151 rec->start = alias;
152 rec->entry = generator_->NewCodeEntry(security_token_id);
153 rec->code_start = start;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000154 events_buffer_.Enqueue(evt_rec);
155}
156
157
158void ProfilerEventsProcessor::FunctionMoveEvent(Address from, Address to) {
159 CodeMoveEvent(from, to);
160}
161
162
163void ProfilerEventsProcessor::FunctionDeleteEvent(Address from) {
164 CodeDeleteEvent(from);
165}
166
167
ager@chromium.org357bf652010-04-12 11:30:10 +0000168void ProfilerEventsProcessor::RegExpCodeCreateEvent(
169 Logger::LogEventsAndTags tag,
170 const char* prefix,
171 String* name,
172 Address start,
173 unsigned size) {
174 if (FilterOutCodeCreateEvent(tag)) return;
175 CodeEventsContainer evt_rec;
176 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
177 rec->type = CodeEventRecord::CODE_CREATION;
178 rec->order = ++enqueue_order_;
179 rec->start = start;
180 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
181 rec->size = size;
182 events_buffer_.Enqueue(evt_rec);
183}
184
185
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000186void ProfilerEventsProcessor::AddCurrentStack() {
187 TickSampleEventRecord record;
188 TickSample* sample = &record.sample;
189 sample->state = VMState::current_state();
190 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
191 sample->frames_count = 0;
192 for (StackTraceFrameIterator it;
193 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
194 it.Advance()) {
195 JavaScriptFrame* frame = it.frame();
196 sample->stack[sample->frames_count++] =
197 reinterpret_cast<Address>(frame->function());
198 }
199 record.order = enqueue_order_;
200 ticks_from_vm_buffer_.Enqueue(record);
201}
202
203
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000204bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
205 if (!events_buffer_.IsEmpty()) {
206 CodeEventsContainer record;
207 events_buffer_.Dequeue(&record);
208 switch (record.generic.type) {
209#define PROFILER_TYPE_CASE(type, clss) \
210 case CodeEventRecord::type: \
211 record.clss##_.UpdateCodeMap(generator_->code_map()); \
212 break;
213
214 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
215
216#undef PROFILER_TYPE_CASE
217 default: return true; // Skip record.
218 }
219 *dequeue_order = record.generic.order;
220 return true;
221 }
222 return false;
223}
224
225
226bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
227 while (true) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000228 if (!ticks_from_vm_buffer_.IsEmpty()
229 && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
230 TickSampleEventRecord record;
231 ticks_from_vm_buffer_.Dequeue(&record);
232 generator_->RecordTickSample(record.sample);
233 }
234
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000235 const TickSampleEventRecord* rec =
lrn@chromium.org25156de2010-04-06 13:10:27 +0000236 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000237 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000238 // Make a local copy of tick sample record to ensure that it won't
239 // be modified as we are processing it. This is possible as the
240 // sampler writes w/o any sync to the queue, so if the processor
241 // will get far behind, a record may be modified right under its
242 // feet.
243 TickSampleEventRecord record = *rec;
244 if (record.order == dequeue_order) {
245 // A paranoid check to make sure that we don't get a memory overrun
246 // in case of frames_count having a wild value.
247 if (record.sample.frames_count < 0
248 || record.sample.frames_count >= TickSample::kMaxFramesCount)
249 record.sample.frames_count = 0;
250 generator_->RecordTickSample(record.sample);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000251 ticks_buffer_.FinishDequeue();
252 } else {
253 return true;
254 }
255 }
256}
257
258
259void ProfilerEventsProcessor::Run() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000260 unsigned dequeue_order = 0;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000261
262 while (running_) {
263 // Process ticks until we have any.
264 if (ProcessTicks(dequeue_order)) {
265 // All ticks of the current dequeue_order are processed,
266 // proceed to the next code event.
267 ProcessCodeEvent(&dequeue_order);
268 }
269 YieldCPU();
270 }
271
272 // Process remaining tick events.
273 ticks_buffer_.FlushResidualRecords();
274 // Perform processing until we have tick events, skip remaining code events.
275 while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000276}
277
278
lrn@chromium.org25156de2010-04-06 13:10:27 +0000279CpuProfiler* CpuProfiler::singleton_ = NULL;
280
281void CpuProfiler::StartProfiling(const char* title) {
282 ASSERT(singleton_ != NULL);
283 singleton_->StartCollectingProfile(title);
284}
285
286
287void CpuProfiler::StartProfiling(String* title) {
288 ASSERT(singleton_ != NULL);
289 singleton_->StartCollectingProfile(title);
290}
291
292
293CpuProfile* CpuProfiler::StopProfiling(const char* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000294 return is_profiling() ? singleton_->StopCollectingProfile(title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000295}
296
297
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000298CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
299 return is_profiling() ?
300 singleton_->StopCollectingProfile(security_token, title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000301}
302
303
304int CpuProfiler::GetProfilesCount() {
305 ASSERT(singleton_ != NULL);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000306 // The count of profiles doesn't depend on a security token.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000307 return singleton_->profiles_->Profiles(
308 TokenEnumerator::kNoSecurityToken)->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000309}
310
311
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000312CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000313 ASSERT(singleton_ != NULL);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000314 const int token = singleton_->token_enumerator_->GetTokenId(security_token);
315 return singleton_->profiles_->Profiles(token)->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000316}
317
318
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000319CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000320 ASSERT(singleton_ != NULL);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000321 const int token = singleton_->token_enumerator_->GetTokenId(security_token);
322 return singleton_->profiles_->GetProfile(token, uid);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000323}
324
325
326TickSample* CpuProfiler::TickSampleEvent() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000327 if (CpuProfiler::is_profiling()) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000328 return singleton_->processor_->TickSampleEvent();
329 } else {
330 return NULL;
331 }
332}
333
334
335void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
336 singleton_->processor_->CallbackCreateEvent(
337 Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
338}
339
340
341void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
342 Code* code, const char* comment) {
343 singleton_->processor_->CodeCreateEvent(
344 tag, comment, code->address(), code->ExecutableSize());
345}
346
347
348void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
349 Code* code, String* name) {
350 singleton_->processor_->CodeCreateEvent(
351 tag,
352 name,
353 Heap::empty_string(),
ager@chromium.org357bf652010-04-12 11:30:10 +0000354 v8::CpuProfileNode::kNoLineNumberInfo,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000355 code->address(),
356 code->ExecutableSize());
357}
358
359
360void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
361 Code* code, String* name,
362 String* source, int line) {
363 singleton_->processor_->CodeCreateEvent(
364 tag,
365 name,
366 source,
367 line,
368 code->address(),
369 code->ExecutableSize());
370}
371
372
373void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
374 Code* code, int args_count) {
375 singleton_->processor_->CodeCreateEvent(
376 tag,
377 args_count,
378 code->address(),
379 code->ExecutableSize());
380}
381
382
383void CpuProfiler::CodeMoveEvent(Address from, Address to) {
384 singleton_->processor_->CodeMoveEvent(from, to);
385}
386
387
388void CpuProfiler::CodeDeleteEvent(Address from) {
389 singleton_->processor_->CodeDeleteEvent(from);
390}
391
392
393void CpuProfiler::FunctionCreateEvent(JSFunction* function) {
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000394 int security_token_id = TokenEnumerator::kNoSecurityToken;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000395 if (function->unchecked_context()->IsContext()) {
396 security_token_id = singleton_->token_enumerator_->GetTokenId(
397 function->context()->global_context()->security_token());
398 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000399 singleton_->processor_->FunctionCreateEvent(
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000400 function->address(),
401 function->code()->address(),
402 security_token_id);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000403}
404
405
406void CpuProfiler::FunctionMoveEvent(Address from, Address to) {
407 singleton_->processor_->FunctionMoveEvent(from, to);
408}
409
410
411void CpuProfiler::FunctionDeleteEvent(Address from) {
412 singleton_->processor_->FunctionDeleteEvent(from);
413}
414
415
416void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
417 singleton_->processor_->CallbackCreateEvent(
418 Logger::CALLBACK_TAG, "get ", name, entry_point);
419}
420
421
422void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000423 singleton_->processor_->RegExpCodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000424 Logger::REG_EXP_TAG,
ager@chromium.org357bf652010-04-12 11:30:10 +0000425 "RegExp: ",
lrn@chromium.org25156de2010-04-06 13:10:27 +0000426 source,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000427 code->address(),
428 code->ExecutableSize());
429}
430
431
432void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
433 singleton_->processor_->CallbackCreateEvent(
434 Logger::CALLBACK_TAG, "set ", name, entry_point);
435}
436
437
438CpuProfiler::CpuProfiler()
439 : profiles_(new CpuProfilesCollection()),
440 next_profile_uid_(1),
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000441 token_enumerator_(new TokenEnumerator()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000442 generator_(NULL),
443 processor_(NULL) {
444}
445
446
447CpuProfiler::~CpuProfiler() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000448 delete token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000449 delete profiles_;
450}
451
452
453void CpuProfiler::StartCollectingProfile(const char* title) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000454 if (profiles_->StartProfiling(title, next_profile_uid_++)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000455 StartProcessorIfNotStarted();
456 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000457 processor_->AddCurrentStack();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000458}
459
460
461void CpuProfiler::StartCollectingProfile(String* title) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000462 StartCollectingProfile(profiles_->GetName(title));
lrn@chromium.org25156de2010-04-06 13:10:27 +0000463}
464
465
466void CpuProfiler::StartProcessorIfNotStarted() {
467 if (processor_ == NULL) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000468 // Disable logging when using the new implementation.
469 saved_logging_nesting_ = Logger::logging_nesting_;
470 Logger::logging_nesting_ = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000471 generator_ = new ProfileGenerator(profiles_);
472 processor_ = new ProfilerEventsProcessor(generator_);
473 processor_->Start();
474 // Enumerate stuff we already have in the heap.
475 if (Heap::HasBeenSetup()) {
476 Logger::LogCodeObjects();
477 Logger::LogCompiledFunctions();
478 Logger::LogFunctionObjects();
479 Logger::LogAccessorCallbacks();
480 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000481 // Enable stack sampling.
482 reinterpret_cast<Sampler*>(Logger::ticker_)->Start();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000483 }
484}
485
486
487CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000488 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000489 StopProcessorIfLastProfile(title);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000490 CpuProfile* result =
491 profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
492 title,
493 actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000494 if (result != NULL) {
495 result->Print();
496 }
497 return result;
498}
499
500
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000501CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
502 String* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000503 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000504 const char* profile_title = profiles_->GetName(title);
505 StopProcessorIfLastProfile(profile_title);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000506 int token = token_enumerator_->GetTokenId(security_token);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000507 return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000508}
509
510
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000511void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
512 if (profiles_->IsLastProfile(title)) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000513 reinterpret_cast<Sampler*>(Logger::ticker_)->Stop();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000514 processor_->Stop();
515 processor_->Join();
516 delete processor_;
517 delete generator_;
518 processor_ = NULL;
519 generator_ = NULL;
ager@chromium.org357bf652010-04-12 11:30:10 +0000520 Logger::logging_nesting_ = saved_logging_nesting_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000521 }
522}
523
524} } // namespace v8::internal
525
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000526#endif // ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +0000527
528namespace v8 {
529namespace internal {
530
531void CpuProfiler::Setup() {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000532#ifdef ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +0000533 if (singleton_ == NULL) {
534 singleton_ = new CpuProfiler();
535 }
536#endif
537}
538
539
540void CpuProfiler::TearDown() {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000541#ifdef ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +0000542 if (singleton_ != NULL) {
543 delete singleton_;
544 }
545 singleton_ = NULL;
546#endif
547}
548
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000549} } // namespace v8::internal