blob: d74c034ac53a0a68b74feef3b09e00398fa019a6 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// 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
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010032#include "frames-inl.h"
Kristian Monsen0d5e1162010-09-30 15:31:59 +010033#include "hashmap.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034#include "log-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010035#include "vm-state-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036
37#include "../include/v8-profiler.h"
38
39namespace v8 {
40namespace internal {
41
42static const int kEventsBufferSize = 256*KB;
43static const int kTickSamplesBufferChunkSize = 64*KB;
44static const int kTickSamplesBufferChunksCount = 16;
45
46
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000047ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
48 : Thread("v8:ProfEvntProc"),
Steve Block9fac8402011-05-12 15:51:54 +010049 generator_(generator),
Steve Block791712a2010-08-27 10:21:07 +010050 running_(true),
Steve Block6ded16b2010-05-10 14:33:55 +010051 ticks_buffer_(sizeof(TickSampleEventRecord),
52 kTickSamplesBufferChunkSize,
53 kTickSamplesBufferChunksCount),
Ben Murdoche0cee9b2011-05-25 10:26:03 +010054 enqueue_order_(0) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010055}
Steve Block6ded16b2010-05-10 14:33:55 +010056
57
58void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
59 const char* prefix,
60 String* name,
61 Address start) {
62 if (FilterOutCodeCreateEvent(tag)) return;
63 CodeEventsContainer evt_rec;
64 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
65 rec->type = CodeEventRecord::CODE_CREATION;
66 rec->order = ++enqueue_order_;
67 rec->start = start;
68 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
69 rec->size = 1;
Steve Block44f0eee2011-05-26 01:26:41 +010070 rec->shared = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +010071 events_buffer_.Enqueue(evt_rec);
72}
73
74
75void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
76 String* name,
77 String* resource_name,
78 int line_number,
79 Address start,
Ben Murdoche0cee9b2011-05-25 10:26:03 +010080 unsigned size,
Steve Block44f0eee2011-05-26 01:26:41 +010081 Address shared) {
Steve Block6ded16b2010-05-10 14:33:55 +010082 if (FilterOutCodeCreateEvent(tag)) return;
83 CodeEventsContainer evt_rec;
84 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
85 rec->type = CodeEventRecord::CODE_CREATION;
86 rec->order = ++enqueue_order_;
87 rec->start = start;
88 rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
89 rec->size = size;
Steve Block44f0eee2011-05-26 01:26:41 +010090 rec->shared = shared;
Steve Block6ded16b2010-05-10 14:33:55 +010091 events_buffer_.Enqueue(evt_rec);
92}
93
94
95void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
96 const char* name,
97 Address start,
98 unsigned size) {
99 if (FilterOutCodeCreateEvent(tag)) return;
100 CodeEventsContainer evt_rec;
101 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
102 rec->type = CodeEventRecord::CODE_CREATION;
103 rec->order = ++enqueue_order_;
104 rec->start = start;
105 rec->entry = generator_->NewCodeEntry(tag, name);
106 rec->size = size;
Steve Block44f0eee2011-05-26 01:26:41 +0100107 rec->shared = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +0100108 events_buffer_.Enqueue(evt_rec);
109}
110
111
112void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
113 int args_count,
114 Address start,
115 unsigned size) {
116 if (FilterOutCodeCreateEvent(tag)) return;
117 CodeEventsContainer evt_rec;
118 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
119 rec->type = CodeEventRecord::CODE_CREATION;
120 rec->order = ++enqueue_order_;
121 rec->start = start;
122 rec->entry = generator_->NewCodeEntry(tag, args_count);
123 rec->size = size;
Steve Block44f0eee2011-05-26 01:26:41 +0100124 rec->shared = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +0100125 events_buffer_.Enqueue(evt_rec);
126}
127
128
129void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
130 CodeEventsContainer evt_rec;
131 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
132 rec->type = CodeEventRecord::CODE_MOVE;
133 rec->order = ++enqueue_order_;
134 rec->from = from;
135 rec->to = to;
136 events_buffer_.Enqueue(evt_rec);
137}
138
139
Steve Block44f0eee2011-05-26 01:26:41 +0100140void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
141 Address to) {
Steve Block6ded16b2010-05-10 14:33:55 +0100142 CodeEventsContainer evt_rec;
Steve Block44f0eee2011-05-26 01:26:41 +0100143 SharedFunctionInfoMoveEventRecord* rec =
144 &evt_rec.SharedFunctionInfoMoveEventRecord_;
145 rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
Steve Block6ded16b2010-05-10 14:33:55 +0100146 rec->order = ++enqueue_order_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100147 rec->from = from;
148 rec->to = to;
Steve Block6ded16b2010-05-10 14:33:55 +0100149 events_buffer_.Enqueue(evt_rec);
Ben Murdochf87a2032010-10-22 12:50:53 +0100150}
151
152
Steve Block6ded16b2010-05-10 14:33:55 +0100153void ProfilerEventsProcessor::RegExpCodeCreateEvent(
154 Logger::LogEventsAndTags tag,
155 const char* prefix,
156 String* name,
157 Address start,
158 unsigned size) {
159 if (FilterOutCodeCreateEvent(tag)) return;
160 CodeEventsContainer evt_rec;
161 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
162 rec->type = CodeEventRecord::CODE_CREATION;
163 rec->order = ++enqueue_order_;
164 rec->start = start;
165 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
166 rec->size = size;
167 events_buffer_.Enqueue(evt_rec);
168}
169
170
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100171void ProfilerEventsProcessor::AddCurrentStack() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000172 TickSampleEventRecord record(enqueue_order_);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100173 TickSample* sample = &record.sample;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100174 Isolate* isolate = Isolate::Current();
175 sample->state = isolate->current_vm_state();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100176 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100177 for (StackTraceFrameIterator it(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100178 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
179 it.Advance()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100180 sample->stack[sample->frames_count++] = it.frame()->pc();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100181 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100182 ticks_from_vm_buffer_.Enqueue(record);
183}
184
185
Steve Block6ded16b2010-05-10 14:33:55 +0100186bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
187 if (!events_buffer_.IsEmpty()) {
188 CodeEventsContainer record;
189 events_buffer_.Dequeue(&record);
190 switch (record.generic.type) {
191#define PROFILER_TYPE_CASE(type, clss) \
192 case CodeEventRecord::type: \
193 record.clss##_.UpdateCodeMap(generator_->code_map()); \
194 break;
195
196 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
197
198#undef PROFILER_TYPE_CASE
199 default: return true; // Skip record.
200 }
201 *dequeue_order = record.generic.order;
202 return true;
203 }
204 return false;
205}
206
207
208bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
209 while (true) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100210 if (!ticks_from_vm_buffer_.IsEmpty()
211 && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
212 TickSampleEventRecord record;
213 ticks_from_vm_buffer_.Dequeue(&record);
214 generator_->RecordTickSample(record.sample);
215 }
216
Steve Block6ded16b2010-05-10 14:33:55 +0100217 const TickSampleEventRecord* rec =
218 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100219 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100220 // Make a local copy of tick sample record to ensure that it won't
221 // be modified as we are processing it. This is possible as the
222 // sampler writes w/o any sync to the queue, so if the processor
223 // will get far behind, a record may be modified right under its
224 // feet.
225 TickSampleEventRecord record = *rec;
226 if (record.order == dequeue_order) {
227 // A paranoid check to make sure that we don't get a memory overrun
228 // in case of frames_count having a wild value.
229 if (record.sample.frames_count < 0
Steve Block053d10c2011-06-13 19:13:29 +0100230 || record.sample.frames_count > TickSample::kMaxFramesCount)
Iain Merrick9ac36c92010-09-13 15:29:50 +0100231 record.sample.frames_count = 0;
232 generator_->RecordTickSample(record.sample);
Steve Block6ded16b2010-05-10 14:33:55 +0100233 ticks_buffer_.FinishDequeue();
234 } else {
235 return true;
236 }
237 }
238}
239
240
241void ProfilerEventsProcessor::Run() {
242 unsigned dequeue_order = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100243
244 while (running_) {
245 // Process ticks until we have any.
246 if (ProcessTicks(dequeue_order)) {
247 // All ticks of the current dequeue_order are processed,
248 // proceed to the next code event.
249 ProcessCodeEvent(&dequeue_order);
250 }
251 YieldCPU();
252 }
253
254 // Process remaining tick events.
255 ticks_buffer_.FlushResidualRecords();
256 // Perform processing until we have tick events, skip remaining code events.
257 while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
258}
259
260
Steve Block6ded16b2010-05-10 14:33:55 +0100261void CpuProfiler::StartProfiling(const char* title) {
Steve Block44f0eee2011-05-26 01:26:41 +0100262 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
263 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
Steve Block6ded16b2010-05-10 14:33:55 +0100264}
265
266
267void CpuProfiler::StartProfiling(String* title) {
Steve Block44f0eee2011-05-26 01:26:41 +0100268 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
269 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
Steve Block6ded16b2010-05-10 14:33:55 +0100270}
271
272
273CpuProfile* CpuProfiler::StopProfiling(const char* title) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000274 Isolate* isolate = Isolate::Current();
275 return is_profiling(isolate) ?
276 isolate->cpu_profiler()->StopCollectingProfile(title) : NULL;
Steve Block6ded16b2010-05-10 14:33:55 +0100277}
278
279
Leon Clarkef7060e22010-06-03 12:02:55 +0100280CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000281 Isolate* isolate = Isolate::Current();
282 return is_profiling(isolate) ?
283 isolate->cpu_profiler()->StopCollectingProfile(
Steve Block44f0eee2011-05-26 01:26:41 +0100284 security_token, title) : NULL;
Steve Block6ded16b2010-05-10 14:33:55 +0100285}
286
287
288int CpuProfiler::GetProfilesCount() {
Steve Block44f0eee2011-05-26 01:26:41 +0100289 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100290 // The count of profiles doesn't depend on a security token.
Steve Block44f0eee2011-05-26 01:26:41 +0100291 return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100292 TokenEnumerator::kNoSecurityToken)->length();
Steve Block6ded16b2010-05-10 14:33:55 +0100293}
294
295
Leon Clarkef7060e22010-06-03 12:02:55 +0100296CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100297 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
298 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
299 const int token = profiler->token_enumerator_->GetTokenId(security_token);
300 return profiler->profiles_->Profiles(token)->at(index);
Steve Block6ded16b2010-05-10 14:33:55 +0100301}
302
303
Leon Clarkef7060e22010-06-03 12:02:55 +0100304CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
Steve Block44f0eee2011-05-26 01:26:41 +0100305 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
306 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
307 const int token = profiler->token_enumerator_->GetTokenId(security_token);
308 return profiler->profiles_->GetProfile(token, uid);
Steve Block6ded16b2010-05-10 14:33:55 +0100309}
310
311
Steve Block44f0eee2011-05-26 01:26:41 +0100312TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
313 if (CpuProfiler::is_profiling(isolate)) {
314 return isolate->cpu_profiler()->processor_->TickSampleEvent();
Steve Block6ded16b2010-05-10 14:33:55 +0100315 } else {
316 return NULL;
317 }
318}
319
320
Steve Block44f0eee2011-05-26 01:26:41 +0100321void CpuProfiler::DeleteAllProfiles() {
322 Isolate* isolate = Isolate::Current();
323 ASSERT(isolate->cpu_profiler() != NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +0000324 if (is_profiling(isolate)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100325 isolate->cpu_profiler()->StopProcessor();
Ben Murdoch257744e2011-11-30 15:57:28 +0000326 }
Steve Block44f0eee2011-05-26 01:26:41 +0100327 isolate->cpu_profiler()->ResetProfiles();
328}
329
330
331void CpuProfiler::DeleteProfile(CpuProfile* profile) {
332 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
333 Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
334 delete profile;
335}
336
337
338bool CpuProfiler::HasDetachedProfiles() {
339 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
340 return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
341}
342
343
Steve Block6ded16b2010-05-10 14:33:55 +0100344void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
Steve Block44f0eee2011-05-26 01:26:41 +0100345 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100346 Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
347}
348
349
350void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
351 Code* code, const char* comment) {
Steve Block44f0eee2011-05-26 01:26:41 +0100352 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100353 tag, comment, code->address(), code->ExecutableSize());
354}
355
356
357void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
358 Code* code, String* name) {
Steve Block44f0eee2011-05-26 01:26:41 +0100359 Isolate* isolate = Isolate::Current();
360 isolate->cpu_profiler()->processor_->CodeCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100361 tag,
362 name,
Steve Block44f0eee2011-05-26 01:26:41 +0100363 isolate->heap()->empty_string(),
Steve Block6ded16b2010-05-10 14:33:55 +0100364 v8::CpuProfileNode::kNoLineNumberInfo,
365 code->address(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100366 code->ExecutableSize(),
367 NULL);
Steve Block6ded16b2010-05-10 14:33:55 +0100368}
369
370
371void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100372 Code* code,
373 SharedFunctionInfo* shared,
374 String* name) {
Steve Block44f0eee2011-05-26 01:26:41 +0100375 Isolate* isolate = Isolate::Current();
376 isolate->cpu_profiler()->processor_->CodeCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100377 tag,
378 name,
Steve Block44f0eee2011-05-26 01:26:41 +0100379 isolate->heap()->empty_string(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100380 v8::CpuProfileNode::kNoLineNumberInfo,
381 code->address(),
382 code->ExecutableSize(),
383 shared->address());
384}
385
386
387void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
388 Code* code,
389 SharedFunctionInfo* shared,
390 String* source, int line) {
Steve Block44f0eee2011-05-26 01:26:41 +0100391 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100392 tag,
393 shared->DebugName(),
Steve Block6ded16b2010-05-10 14:33:55 +0100394 source,
395 line,
396 code->address(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100397 code->ExecutableSize(),
398 shared->address());
Steve Block6ded16b2010-05-10 14:33:55 +0100399}
400
401
402void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
403 Code* code, int args_count) {
Steve Block44f0eee2011-05-26 01:26:41 +0100404 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100405 tag,
406 args_count,
407 code->address(),
408 code->ExecutableSize());
409}
410
411
412void CpuProfiler::CodeMoveEvent(Address from, Address to) {
Steve Block44f0eee2011-05-26 01:26:41 +0100413 Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
Steve Block6ded16b2010-05-10 14:33:55 +0100414}
415
416
417void CpuProfiler::CodeDeleteEvent(Address from) {
Steve Block6ded16b2010-05-10 14:33:55 +0100418}
419
420
Steve Block44f0eee2011-05-26 01:26:41 +0100421void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
422 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
423 profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
Steve Block6ded16b2010-05-10 14:33:55 +0100424}
425
426
427void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
Steve Block44f0eee2011-05-26 01:26:41 +0100428 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100429 Logger::CALLBACK_TAG, "get ", name, entry_point);
430}
431
432
433void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
Steve Block44f0eee2011-05-26 01:26:41 +0100434 Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100435 Logger::REG_EXP_TAG,
436 "RegExp: ",
437 source,
438 code->address(),
439 code->ExecutableSize());
440}
441
442
443void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
Steve Block44f0eee2011-05-26 01:26:41 +0100444 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Steve Block6ded16b2010-05-10 14:33:55 +0100445 Logger::CALLBACK_TAG, "set ", name, entry_point);
446}
447
448
449CpuProfiler::CpuProfiler()
450 : profiles_(new CpuProfilesCollection()),
451 next_profile_uid_(1),
Leon Clarkef7060e22010-06-03 12:02:55 +0100452 token_enumerator_(new TokenEnumerator()),
Steve Block6ded16b2010-05-10 14:33:55 +0100453 generator_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +0100454 processor_(NULL),
455 need_to_stop_sampler_(false),
456 is_profiling_(false) {
Steve Block6ded16b2010-05-10 14:33:55 +0100457}
458
459
460CpuProfiler::~CpuProfiler() {
Leon Clarkef7060e22010-06-03 12:02:55 +0100461 delete token_enumerator_;
Steve Block6ded16b2010-05-10 14:33:55 +0100462 delete profiles_;
463}
464
465
Steve Block44f0eee2011-05-26 01:26:41 +0100466void CpuProfiler::ResetProfiles() {
467 delete profiles_;
468 profiles_ = new CpuProfilesCollection();
469}
470
Steve Block6ded16b2010-05-10 14:33:55 +0100471void CpuProfiler::StartCollectingProfile(const char* title) {
472 if (profiles_->StartProfiling(title, next_profile_uid_++)) {
473 StartProcessorIfNotStarted();
474 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100475 processor_->AddCurrentStack();
Steve Block6ded16b2010-05-10 14:33:55 +0100476}
477
478
479void CpuProfiler::StartCollectingProfile(String* title) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100480 StartCollectingProfile(profiles_->GetName(title));
Steve Block6ded16b2010-05-10 14:33:55 +0100481}
482
483
484void CpuProfiler::StartProcessorIfNotStarted() {
485 if (processor_ == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100486 Isolate* isolate = Isolate::Current();
487
Steve Block6ded16b2010-05-10 14:33:55 +0100488 // Disable logging when using the new implementation.
Steve Block44f0eee2011-05-26 01:26:41 +0100489 saved_logging_nesting_ = isolate->logger()->logging_nesting_;
490 isolate->logger()->logging_nesting_ = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100491 generator_ = new ProfileGenerator(profiles_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000492 processor_ = new ProfilerEventsProcessor(generator_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100493 NoBarrier_Store(&is_profiling_, true);
Steve Block6ded16b2010-05-10 14:33:55 +0100494 processor_->Start();
Steve Block6ded16b2010-05-10 14:33:55 +0100495 // Enumerate stuff we already have in the heap.
Steve Block44f0eee2011-05-26 01:26:41 +0100496 if (isolate->heap()->HasBeenSetup()) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100497 if (!FLAG_prof_browser_mode) {
498 bool saved_log_code_flag = FLAG_log_code;
499 FLAG_log_code = true;
Steve Block44f0eee2011-05-26 01:26:41 +0100500 isolate->logger()->LogCodeObjects();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100501 FLAG_log_code = saved_log_code_flag;
502 }
Steve Block44f0eee2011-05-26 01:26:41 +0100503 isolate->logger()->LogCompiledFunctions();
504 isolate->logger()->LogAccessorCallbacks();
Steve Block6ded16b2010-05-10 14:33:55 +0100505 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100506 // Enable stack sampling.
Steve Block44f0eee2011-05-26 01:26:41 +0100507 Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
508 if (!sampler->IsActive()) {
509 sampler->Start();
510 need_to_stop_sampler_ = true;
511 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100512 sampler->IncreaseProfilingDepth();
Steve Block6ded16b2010-05-10 14:33:55 +0100513 }
514}
515
516
517CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
518 const double actual_sampling_rate = generator_->actual_sampling_rate();
Iain Merrick75681382010-08-19 15:07:18 +0100519 StopProcessorIfLastProfile(title);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100520 CpuProfile* result =
521 profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
522 title,
523 actual_sampling_rate);
Steve Block6ded16b2010-05-10 14:33:55 +0100524 if (result != NULL) {
525 result->Print();
526 }
527 return result;
528}
529
530
Leon Clarkef7060e22010-06-03 12:02:55 +0100531CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
532 String* title) {
Steve Block6ded16b2010-05-10 14:33:55 +0100533 const double actual_sampling_rate = generator_->actual_sampling_rate();
Iain Merrick75681382010-08-19 15:07:18 +0100534 const char* profile_title = profiles_->GetName(title);
535 StopProcessorIfLastProfile(profile_title);
Leon Clarkef7060e22010-06-03 12:02:55 +0100536 int token = token_enumerator_->GetTokenId(security_token);
Iain Merrick75681382010-08-19 15:07:18 +0100537 return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
Steve Block6ded16b2010-05-10 14:33:55 +0100538}
539
540
Iain Merrick75681382010-08-19 15:07:18 +0100541void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
Steve Block44f0eee2011-05-26 01:26:41 +0100542 if (profiles_->IsLastProfile(title)) StopProcessor();
543}
544
545
546void CpuProfiler::StopProcessor() {
547 Logger* logger = Isolate::Current()->logger();
548 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
549 sampler->DecreaseProfilingDepth();
550 if (need_to_stop_sampler_) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100551 sampler->Stop();
Steve Block44f0eee2011-05-26 01:26:41 +0100552 need_to_stop_sampler_ = false;
Steve Block6ded16b2010-05-10 14:33:55 +0100553 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000554 NoBarrier_Store(&is_profiling_, false);
Steve Block44f0eee2011-05-26 01:26:41 +0100555 processor_->Stop();
556 processor_->Join();
557 delete processor_;
558 delete generator_;
559 processor_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +0100560 generator_ = NULL;
561 logger->logging_nesting_ = saved_logging_nesting_;
Steve Block6ded16b2010-05-10 14:33:55 +0100562}
563
Steve Block6ded16b2010-05-10 14:33:55 +0100564
565void CpuProfiler::Setup() {
Steve Block44f0eee2011-05-26 01:26:41 +0100566 Isolate* isolate = Isolate::Current();
567 if (isolate->cpu_profiler() == NULL) {
568 isolate->set_cpu_profiler(new CpuProfiler());
Steve Block6ded16b2010-05-10 14:33:55 +0100569 }
Steve Block6ded16b2010-05-10 14:33:55 +0100570}
571
572
573void CpuProfiler::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +0100574 Isolate* isolate = Isolate::Current();
575 if (isolate->cpu_profiler() != NULL) {
576 delete isolate->cpu_profiler();
Steve Block6ded16b2010-05-10 14:33:55 +0100577 }
Steve Block44f0eee2011-05-26 01:26:41 +0100578 isolate->set_cpu_profiler(NULL);
Steve Block6ded16b2010-05-10 14:33:55 +0100579}
580
581} } // namespace v8::internal