blob: 8d11e7a00b7e60a6da6cac1c1a1a57e4b7b97740 [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"
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000035#include "hashmap.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000036#include "log-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "vm-state-inl.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000038
ager@chromium.org357bf652010-04-12 11:30:10 +000039#include "../include/v8-profiler.h"
40
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000041namespace v8 {
42namespace internal {
43
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000044static const int kEventsBufferSize = 256*KB;
45static const int kTickSamplesBufferChunkSize = 64*KB;
46static const int kTickSamplesBufferChunksCount = 16;
47
48
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000049ProfilerEventsProcessor::ProfilerEventsProcessor(Isolate* isolate,
50 ProfileGenerator* generator)
51 : Thread(isolate, "v8:ProfEvntProc"),
lrn@chromium.org5d00b602011-01-05 09:51:43 +000052 generator_(generator),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000053 running_(true),
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000054 ticks_buffer_(sizeof(TickSampleEventRecord),
55 kTickSamplesBufferChunkSize,
56 kTickSamplesBufferChunksCount),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000057 enqueue_order_(0) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000058}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000059
60
lrn@chromium.org25156de2010-04-06 13:10:27 +000061void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
62 const char* prefix,
63 String* name,
64 Address start) {
ager@chromium.org357bf652010-04-12 11:30:10 +000065 if (FilterOutCodeCreateEvent(tag)) return;
lrn@chromium.org25156de2010-04-06 13:10:27 +000066 CodeEventsContainer evt_rec;
67 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
68 rec->type = CodeEventRecord::CODE_CREATION;
69 rec->order = ++enqueue_order_;
70 rec->start = start;
71 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
72 rec->size = 1;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000073 rec->shared = NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +000074 events_buffer_.Enqueue(evt_rec);
75}
76
77
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000078void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
79 String* name,
80 String* resource_name,
81 int line_number,
82 Address start,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000083 unsigned size,
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000084 Address shared) {
ager@chromium.org357bf652010-04-12 11:30:10 +000085 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000086 CodeEventsContainer evt_rec;
87 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
88 rec->type = CodeEventRecord::CODE_CREATION;
89 rec->order = ++enqueue_order_;
90 rec->start = start;
91 rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
92 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000093 rec->shared = shared;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000094 events_buffer_.Enqueue(evt_rec);
95}
96
97
98void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
99 const char* name,
100 Address start,
101 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000102 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000103 CodeEventsContainer evt_rec;
104 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
105 rec->type = CodeEventRecord::CODE_CREATION;
106 rec->order = ++enqueue_order_;
107 rec->start = start;
108 rec->entry = generator_->NewCodeEntry(tag, name);
109 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000110 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000111 events_buffer_.Enqueue(evt_rec);
112}
113
114
115void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
116 int args_count,
117 Address start,
118 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000119 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000120 CodeEventsContainer evt_rec;
121 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
122 rec->type = CodeEventRecord::CODE_CREATION;
123 rec->order = ++enqueue_order_;
124 rec->start = start;
125 rec->entry = generator_->NewCodeEntry(tag, args_count);
126 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000127 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000128 events_buffer_.Enqueue(evt_rec);
129}
130
131
132void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
133 CodeEventsContainer evt_rec;
134 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
135 rec->type = CodeEventRecord::CODE_MOVE;
136 rec->order = ++enqueue_order_;
137 rec->from = from;
138 rec->to = to;
139 events_buffer_.Enqueue(evt_rec);
140}
141
142
143void ProfilerEventsProcessor::CodeDeleteEvent(Address from) {
144 CodeEventsContainer evt_rec;
145 CodeDeleteEventRecord* rec = &evt_rec.CodeDeleteEventRecord_;
146 rec->type = CodeEventRecord::CODE_DELETE;
147 rec->order = ++enqueue_order_;
148 rec->start = from;
149 events_buffer_.Enqueue(evt_rec);
150}
151
152
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000153void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
154 Address to) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000155 CodeEventsContainer evt_rec;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000156 SharedFunctionInfoMoveEventRecord* rec =
157 &evt_rec.SharedFunctionInfoMoveEventRecord_;
158 rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000159 rec->order = ++enqueue_order_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000160 rec->from = from;
161 rec->to = to;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000162 events_buffer_.Enqueue(evt_rec);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000163}
164
165
ager@chromium.org357bf652010-04-12 11:30:10 +0000166void ProfilerEventsProcessor::RegExpCodeCreateEvent(
167 Logger::LogEventsAndTags tag,
168 const char* prefix,
169 String* name,
170 Address start,
171 unsigned size) {
172 if (FilterOutCodeCreateEvent(tag)) return;
173 CodeEventsContainer evt_rec;
174 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
175 rec->type = CodeEventRecord::CODE_CREATION;
176 rec->order = ++enqueue_order_;
177 rec->start = start;
178 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
179 rec->size = size;
180 events_buffer_.Enqueue(evt_rec);
181}
182
183
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000184void ProfilerEventsProcessor::AddCurrentStack() {
185 TickSampleEventRecord record;
186 TickSample* sample = &record.sample;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000187 Isolate* isolate = Isolate::Current();
188 sample->state = isolate->current_vm_state();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000189 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000190 sample->tos = NULL;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000191 sample->has_external_callback = false;
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000192 sample->frames_count = 0;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000193 for (StackTraceFrameIterator it(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000194 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
195 it.Advance()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000196 sample->stack[sample->frames_count++] = it.frame()->pc();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000197 }
198 record.order = enqueue_order_;
199 ticks_from_vm_buffer_.Enqueue(record);
200}
201
202
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000203bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
204 if (!events_buffer_.IsEmpty()) {
205 CodeEventsContainer record;
206 events_buffer_.Dequeue(&record);
207 switch (record.generic.type) {
208#define PROFILER_TYPE_CASE(type, clss) \
209 case CodeEventRecord::type: \
210 record.clss##_.UpdateCodeMap(generator_->code_map()); \
211 break;
212
213 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
214
215#undef PROFILER_TYPE_CASE
216 default: return true; // Skip record.
217 }
218 *dequeue_order = record.generic.order;
219 return true;
220 }
221 return false;
222}
223
224
225bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
226 while (true) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000227 if (!ticks_from_vm_buffer_.IsEmpty()
228 && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
229 TickSampleEventRecord record;
230 ticks_from_vm_buffer_.Dequeue(&record);
231 generator_->RecordTickSample(record.sample);
232 }
233
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000234 const TickSampleEventRecord* rec =
lrn@chromium.org25156de2010-04-06 13:10:27 +0000235 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000236 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000237 // Make a local copy of tick sample record to ensure that it won't
238 // be modified as we are processing it. This is possible as the
239 // sampler writes w/o any sync to the queue, so if the processor
240 // will get far behind, a record may be modified right under its
241 // feet.
242 TickSampleEventRecord record = *rec;
243 if (record.order == dequeue_order) {
244 // A paranoid check to make sure that we don't get a memory overrun
245 // in case of frames_count having a wild value.
246 if (record.sample.frames_count < 0
247 || record.sample.frames_count >= TickSample::kMaxFramesCount)
248 record.sample.frames_count = 0;
249 generator_->RecordTickSample(record.sample);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000250 ticks_buffer_.FinishDequeue();
251 } else {
252 return true;
253 }
254 }
255}
256
257
258void ProfilerEventsProcessor::Run() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000259 unsigned dequeue_order = 0;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000260
261 while (running_) {
262 // Process ticks until we have any.
263 if (ProcessTicks(dequeue_order)) {
264 // All ticks of the current dequeue_order are processed,
265 // proceed to the next code event.
266 ProcessCodeEvent(&dequeue_order);
267 }
268 YieldCPU();
269 }
270
271 // Process remaining tick events.
272 ticks_buffer_.FlushResidualRecords();
273 // Perform processing until we have tick events, skip remaining code events.
274 while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000275}
276
277
lrn@chromium.org25156de2010-04-06 13:10:27 +0000278void CpuProfiler::StartProfiling(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000279 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
280 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000281}
282
283
284void CpuProfiler::StartProfiling(String* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000285 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
286 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000287}
288
289
290CpuProfile* CpuProfiler::StopProfiling(const char* title) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000291 Isolate* isolate = Isolate::Current();
292 return is_profiling(isolate) ?
293 isolate->cpu_profiler()->StopCollectingProfile(title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000294}
295
296
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000297CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000298 Isolate* isolate = Isolate::Current();
299 return is_profiling(isolate) ?
300 isolate->cpu_profiler()->StopCollectingProfile(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000301 security_token, title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000302}
303
304
305int CpuProfiler::GetProfilesCount() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000306 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000307 // The count of profiles doesn't depend on a security token.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000308 return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000309 TokenEnumerator::kNoSecurityToken)->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000310}
311
312
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000313CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000314 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
315 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
316 const int token = profiler->token_enumerator_->GetTokenId(security_token);
317 return profiler->profiles_->Profiles(token)->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000318}
319
320
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000321CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000322 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
323 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
324 const int token = profiler->token_enumerator_->GetTokenId(security_token);
325 return profiler->profiles_->GetProfile(token, uid);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000326}
327
328
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000329TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
330 if (CpuProfiler::is_profiling(isolate)) {
331 return isolate->cpu_profiler()->processor_->TickSampleEvent();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000332 } else {
333 return NULL;
334 }
335}
336
337
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000338void CpuProfiler::DeleteAllProfiles() {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000339 Isolate* isolate = Isolate::Current();
340 ASSERT(isolate->cpu_profiler() != NULL);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000341 if (is_profiling(isolate)) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000342 isolate->cpu_profiler()->StopProcessor();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000343 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000344 isolate->cpu_profiler()->ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000345}
346
347
348void CpuProfiler::DeleteProfile(CpuProfile* profile) {
349 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
350 Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
351 delete profile;
352}
353
354
355bool CpuProfiler::HasDetachedProfiles() {
356 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
357 return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
358}
359
360
lrn@chromium.org25156de2010-04-06 13:10:27 +0000361void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000362 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000363 Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
364}
365
366
367void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
368 Code* code, const char* comment) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000369 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000370 tag, comment, code->address(), code->ExecutableSize());
371}
372
373
374void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
375 Code* code, String* name) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000376 Isolate* isolate = Isolate::Current();
377 isolate->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000378 tag,
379 name,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000380 isolate->heap()->empty_string(),
ager@chromium.org357bf652010-04-12 11:30:10 +0000381 v8::CpuProfileNode::kNoLineNumberInfo,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000382 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000383 code->ExecutableSize(),
384 NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000385}
386
387
388void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000389 Code* code,
390 SharedFunctionInfo* shared,
391 String* name) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000392 Isolate* isolate = Isolate::Current();
393 isolate->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000394 tag,
395 name,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000396 isolate->heap()->empty_string(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000397 v8::CpuProfileNode::kNoLineNumberInfo,
398 code->address(),
399 code->ExecutableSize(),
400 shared->address());
401}
402
403
404void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
405 Code* code,
406 SharedFunctionInfo* shared,
407 String* source, int line) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000408 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000409 tag,
410 shared->DebugName(),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000411 source,
412 line,
413 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000414 code->ExecutableSize(),
415 shared->address());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000416}
417
418
419void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
420 Code* code, int args_count) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000421 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000422 tag,
423 args_count,
424 code->address(),
425 code->ExecutableSize());
426}
427
428
429void CpuProfiler::CodeMoveEvent(Address from, Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000430 Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000431}
432
433
434void CpuProfiler::CodeDeleteEvent(Address from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000435 Isolate::Current()->cpu_profiler()->processor_->CodeDeleteEvent(from);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000436}
437
438
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000439void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000440 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
441 profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000442}
443
444
445void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000446 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000447 Logger::CALLBACK_TAG, "get ", name, entry_point);
448}
449
450
451void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000452 Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000453 Logger::REG_EXP_TAG,
ager@chromium.org357bf652010-04-12 11:30:10 +0000454 "RegExp: ",
lrn@chromium.org25156de2010-04-06 13:10:27 +0000455 source,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000456 code->address(),
457 code->ExecutableSize());
458}
459
460
461void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000462 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000463 Logger::CALLBACK_TAG, "set ", name, entry_point);
464}
465
466
467CpuProfiler::CpuProfiler()
468 : profiles_(new CpuProfilesCollection()),
469 next_profile_uid_(1),
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000470 token_enumerator_(new TokenEnumerator()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000471 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000472 processor_(NULL),
473 need_to_stop_sampler_(false),
474 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000475}
476
477
478CpuProfiler::~CpuProfiler() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000479 delete token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000480 delete profiles_;
481}
482
483
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000484void CpuProfiler::ResetProfiles() {
485 delete profiles_;
486 profiles_ = new CpuProfilesCollection();
487}
488
lrn@chromium.org25156de2010-04-06 13:10:27 +0000489void CpuProfiler::StartCollectingProfile(const char* title) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000490 if (profiles_->StartProfiling(title, next_profile_uid_++)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000491 StartProcessorIfNotStarted();
492 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000493 processor_->AddCurrentStack();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000494}
495
496
497void CpuProfiler::StartCollectingProfile(String* title) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000498 StartCollectingProfile(profiles_->GetName(title));
lrn@chromium.org25156de2010-04-06 13:10:27 +0000499}
500
501
502void CpuProfiler::StartProcessorIfNotStarted() {
503 if (processor_ == NULL) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000504 Isolate* isolate = Isolate::Current();
505
ager@chromium.org357bf652010-04-12 11:30:10 +0000506 // Disable logging when using the new implementation.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000507 saved_logging_nesting_ = isolate->logger()->logging_nesting_;
508 isolate->logger()->logging_nesting_ = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000509 generator_ = new ProfileGenerator(profiles_);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000510 processor_ = new ProfilerEventsProcessor(isolate, generator_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000511 NoBarrier_Store(&is_profiling_, true);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000512 processor_->Start();
513 // Enumerate stuff we already have in the heap.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000514 if (isolate->heap()->HasBeenSetup()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000515 if (!FLAG_prof_browser_mode) {
516 bool saved_log_code_flag = FLAG_log_code;
517 FLAG_log_code = true;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000518 isolate->logger()->LogCodeObjects();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000519 FLAG_log_code = saved_log_code_flag;
520 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000521 isolate->logger()->LogCompiledFunctions();
522 isolate->logger()->LogAccessorCallbacks();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000523 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000524 // Enable stack sampling.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000525 Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000526 if (!sampler->IsActive()) {
527 sampler->Start();
528 need_to_stop_sampler_ = true;
529 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000530 sampler->IncreaseProfilingDepth();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000531 }
532}
533
534
535CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000536 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000537 StopProcessorIfLastProfile(title);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000538 CpuProfile* result =
539 profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
540 title,
541 actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000542 if (result != NULL) {
543 result->Print();
544 }
545 return result;
546}
547
548
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000549CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
550 String* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000551 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000552 const char* profile_title = profiles_->GetName(title);
553 StopProcessorIfLastProfile(profile_title);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000554 int token = token_enumerator_->GetTokenId(security_token);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000555 return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000556}
557
558
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000559void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000560 if (profiles_->IsLastProfile(title)) StopProcessor();
561}
562
563
564void CpuProfiler::StopProcessor() {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000565 Logger* logger = Isolate::Current()->logger();
566 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000567 sampler->DecreaseProfilingDepth();
568 if (need_to_stop_sampler_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000569 sampler->Stop();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000570 need_to_stop_sampler_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000571 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000572 processor_->Stop();
573 processor_->Join();
574 delete processor_;
575 delete generator_;
576 processor_ = NULL;
577 NoBarrier_Store(&is_profiling_, false);
578 generator_ = NULL;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000579 logger->logging_nesting_ = saved_logging_nesting_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000580}
581
582} } // namespace v8::internal
583
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000584#endif // ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +0000585
586namespace v8 {
587namespace internal {
588
589void CpuProfiler::Setup() {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000590#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000591 Isolate* isolate = Isolate::Current();
592 if (isolate->cpu_profiler() == NULL) {
593 isolate->set_cpu_profiler(new CpuProfiler());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000594 }
595#endif
596}
597
598
599void CpuProfiler::TearDown() {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000600#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000601 Isolate* isolate = Isolate::Current();
602 if (isolate->cpu_profiler() != NULL) {
603 delete isolate->cpu_profiler();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000604 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000605 isolate->set_cpu_profiler(NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000606#endif
607}
608
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000609} } // namespace v8::internal