blob: 8b10e8188cbbe39c261bbe88260a155059b12d67 [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
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000049ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
50 : Thread("v8:ProfEvntProc"),
lrn@chromium.org5d00b602011-01-05 09:51:43 +000051 generator_(generator),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000052 running_(true),
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000053 ticks_buffer_(sizeof(TickSampleEventRecord),
54 kTickSamplesBufferChunkSize,
55 kTickSamplesBufferChunksCount),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000056 enqueue_order_(0) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000057}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000058
59
lrn@chromium.org25156de2010-04-06 13:10:27 +000060void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
61 const char* prefix,
62 String* name,
63 Address start) {
ager@chromium.org357bf652010-04-12 11:30:10 +000064 if (FilterOutCodeCreateEvent(tag)) return;
lrn@chromium.org25156de2010-04-06 13:10:27 +000065 CodeEventsContainer evt_rec;
66 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
67 rec->type = CodeEventRecord::CODE_CREATION;
68 rec->order = ++enqueue_order_;
69 rec->start = start;
70 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
71 rec->size = 1;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000072 rec->shared = NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +000073 events_buffer_.Enqueue(evt_rec);
74}
75
76
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000077void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
78 String* name,
79 String* resource_name,
80 int line_number,
81 Address start,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000082 unsigned size,
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000083 Address shared) {
ager@chromium.org357bf652010-04-12 11:30:10 +000084 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000085 CodeEventsContainer evt_rec;
86 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
87 rec->type = CodeEventRecord::CODE_CREATION;
88 rec->order = ++enqueue_order_;
89 rec->start = start;
90 rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
91 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000092 rec->shared = shared;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000093 events_buffer_.Enqueue(evt_rec);
94}
95
96
97void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
98 const char* name,
99 Address start,
100 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000101 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000102 CodeEventsContainer evt_rec;
103 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
104 rec->type = CodeEventRecord::CODE_CREATION;
105 rec->order = ++enqueue_order_;
106 rec->start = start;
107 rec->entry = generator_->NewCodeEntry(tag, name);
108 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000109 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000110 events_buffer_.Enqueue(evt_rec);
111}
112
113
114void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
115 int args_count,
116 Address start,
117 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000118 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000119 CodeEventsContainer evt_rec;
120 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
121 rec->type = CodeEventRecord::CODE_CREATION;
122 rec->order = ++enqueue_order_;
123 rec->start = start;
124 rec->entry = generator_->NewCodeEntry(tag, args_count);
125 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000126 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000127 events_buffer_.Enqueue(evt_rec);
128}
129
130
131void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
132 CodeEventsContainer evt_rec;
133 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
134 rec->type = CodeEventRecord::CODE_MOVE;
135 rec->order = ++enqueue_order_;
136 rec->from = from;
137 rec->to = to;
138 events_buffer_.Enqueue(evt_rec);
139}
140
141
142void ProfilerEventsProcessor::CodeDeleteEvent(Address from) {
143 CodeEventsContainer evt_rec;
144 CodeDeleteEventRecord* rec = &evt_rec.CodeDeleteEventRecord_;
145 rec->type = CodeEventRecord::CODE_DELETE;
146 rec->order = ++enqueue_order_;
147 rec->start = from;
148 events_buffer_.Enqueue(evt_rec);
149}
150
151
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000152void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
153 Address to) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000154 CodeEventsContainer evt_rec;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000155 SharedFunctionInfoMoveEventRecord* rec =
156 &evt_rec.SharedFunctionInfoMoveEventRecord_;
157 rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000158 rec->order = ++enqueue_order_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000159 rec->from = from;
160 rec->to = to;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000161 events_buffer_.Enqueue(evt_rec);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000162}
163
164
ager@chromium.org357bf652010-04-12 11:30:10 +0000165void ProfilerEventsProcessor::RegExpCodeCreateEvent(
166 Logger::LogEventsAndTags tag,
167 const char* prefix,
168 String* name,
169 Address start,
170 unsigned size) {
171 if (FilterOutCodeCreateEvent(tag)) return;
172 CodeEventsContainer evt_rec;
173 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
174 rec->type = CodeEventRecord::CODE_CREATION;
175 rec->order = ++enqueue_order_;
176 rec->start = start;
177 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
178 rec->size = size;
179 events_buffer_.Enqueue(evt_rec);
180}
181
182
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000183void ProfilerEventsProcessor::AddCurrentStack() {
ager@chromium.org04921a82011-06-27 13:21:41 +0000184 TickSampleEventRecord record(enqueue_order_);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000185 TickSample* sample = &record.sample;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000186 Isolate* isolate = Isolate::Current();
187 sample->state = isolate->current_vm_state();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000188 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000189 for (StackTraceFrameIterator it(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000190 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
191 it.Advance()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000192 sample->stack[sample->frames_count++] = it.frame()->pc();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000193 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000194 ticks_from_vm_buffer_.Enqueue(record);
195}
196
197
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000198bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
199 if (!events_buffer_.IsEmpty()) {
200 CodeEventsContainer record;
201 events_buffer_.Dequeue(&record);
202 switch (record.generic.type) {
203#define PROFILER_TYPE_CASE(type, clss) \
204 case CodeEventRecord::type: \
205 record.clss##_.UpdateCodeMap(generator_->code_map()); \
206 break;
207
208 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
209
210#undef PROFILER_TYPE_CASE
211 default: return true; // Skip record.
212 }
213 *dequeue_order = record.generic.order;
214 return true;
215 }
216 return false;
217}
218
219
220bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
221 while (true) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000222 if (!ticks_from_vm_buffer_.IsEmpty()
223 && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
224 TickSampleEventRecord record;
225 ticks_from_vm_buffer_.Dequeue(&record);
226 generator_->RecordTickSample(record.sample);
227 }
228
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000229 const TickSampleEventRecord* rec =
lrn@chromium.org25156de2010-04-06 13:10:27 +0000230 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000231 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000232 // Make a local copy of tick sample record to ensure that it won't
233 // be modified as we are processing it. This is possible as the
234 // sampler writes w/o any sync to the queue, so if the processor
235 // will get far behind, a record may be modified right under its
236 // feet.
237 TickSampleEventRecord record = *rec;
238 if (record.order == dequeue_order) {
239 // A paranoid check to make sure that we don't get a memory overrun
240 // in case of frames_count having a wild value.
241 if (record.sample.frames_count < 0
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000242 || record.sample.frames_count > TickSample::kMaxFramesCount)
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000243 record.sample.frames_count = 0;
244 generator_->RecordTickSample(record.sample);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000245 ticks_buffer_.FinishDequeue();
246 } else {
247 return true;
248 }
249 }
250}
251
252
253void ProfilerEventsProcessor::Run() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000254 unsigned dequeue_order = 0;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000255
256 while (running_) {
257 // Process ticks until we have any.
258 if (ProcessTicks(dequeue_order)) {
259 // All ticks of the current dequeue_order are processed,
260 // proceed to the next code event.
261 ProcessCodeEvent(&dequeue_order);
262 }
263 YieldCPU();
264 }
265
266 // Process remaining tick events.
267 ticks_buffer_.FlushResidualRecords();
268 // Perform processing until we have tick events, skip remaining code events.
269 while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000270}
271
272
lrn@chromium.org25156de2010-04-06 13:10:27 +0000273void CpuProfiler::StartProfiling(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000274 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
275 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000276}
277
278
279void CpuProfiler::StartProfiling(String* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000280 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
281 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000282}
283
284
285CpuProfile* CpuProfiler::StopProfiling(const char* title) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000286 Isolate* isolate = Isolate::Current();
287 return is_profiling(isolate) ?
288 isolate->cpu_profiler()->StopCollectingProfile(title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000289}
290
291
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000292CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000293 Isolate* isolate = Isolate::Current();
294 return is_profiling(isolate) ?
295 isolate->cpu_profiler()->StopCollectingProfile(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000296 security_token, title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000297}
298
299
300int CpuProfiler::GetProfilesCount() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000301 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000302 // The count of profiles doesn't depend on a security token.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000303 return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000304 TokenEnumerator::kNoSecurityToken)->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000305}
306
307
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000308CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000309 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
310 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
311 const int token = profiler->token_enumerator_->GetTokenId(security_token);
312 return profiler->profiles_->Profiles(token)->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000313}
314
315
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000316CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000317 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
318 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
319 const int token = profiler->token_enumerator_->GetTokenId(security_token);
320 return profiler->profiles_->GetProfile(token, uid);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000321}
322
323
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000324TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
325 if (CpuProfiler::is_profiling(isolate)) {
326 return isolate->cpu_profiler()->processor_->TickSampleEvent();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000327 } else {
328 return NULL;
329 }
330}
331
332
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000333void CpuProfiler::DeleteAllProfiles() {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000334 Isolate* isolate = Isolate::Current();
335 ASSERT(isolate->cpu_profiler() != NULL);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000336 if (is_profiling(isolate)) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000337 isolate->cpu_profiler()->StopProcessor();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000338 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000339 isolate->cpu_profiler()->ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000340}
341
342
343void CpuProfiler::DeleteProfile(CpuProfile* profile) {
344 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
345 Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
346 delete profile;
347}
348
349
350bool CpuProfiler::HasDetachedProfiles() {
351 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
352 return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
353}
354
355
lrn@chromium.org25156de2010-04-06 13:10:27 +0000356void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000357 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000358 Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
359}
360
361
362void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
363 Code* code, const char* comment) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000364 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000365 tag, comment, code->address(), code->ExecutableSize());
366}
367
368
369void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
370 Code* code, String* name) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000371 Isolate* isolate = Isolate::Current();
372 isolate->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000373 tag,
374 name,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000375 isolate->heap()->empty_string(),
ager@chromium.org357bf652010-04-12 11:30:10 +0000376 v8::CpuProfileNode::kNoLineNumberInfo,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000377 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000378 code->ExecutableSize(),
379 NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000380}
381
382
383void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000384 Code* code,
385 SharedFunctionInfo* shared,
386 String* name) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000387 Isolate* isolate = Isolate::Current();
388 isolate->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000389 tag,
390 name,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000391 isolate->heap()->empty_string(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000392 v8::CpuProfileNode::kNoLineNumberInfo,
393 code->address(),
394 code->ExecutableSize(),
395 shared->address());
396}
397
398
399void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
400 Code* code,
401 SharedFunctionInfo* shared,
402 String* source, int line) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000403 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000404 tag,
405 shared->DebugName(),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000406 source,
407 line,
408 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000409 code->ExecutableSize(),
410 shared->address());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000411}
412
413
414void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
415 Code* code, int args_count) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000416 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000417 tag,
418 args_count,
419 code->address(),
420 code->ExecutableSize());
421}
422
423
424void CpuProfiler::CodeMoveEvent(Address from, Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000425 Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000426}
427
428
429void CpuProfiler::CodeDeleteEvent(Address from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000430 Isolate::Current()->cpu_profiler()->processor_->CodeDeleteEvent(from);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000431}
432
433
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000434void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000435 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
436 profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000437}
438
439
440void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000441 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000442 Logger::CALLBACK_TAG, "get ", name, entry_point);
443}
444
445
446void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000447 Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000448 Logger::REG_EXP_TAG,
ager@chromium.org357bf652010-04-12 11:30:10 +0000449 "RegExp: ",
lrn@chromium.org25156de2010-04-06 13:10:27 +0000450 source,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000451 code->address(),
452 code->ExecutableSize());
453}
454
455
456void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000457 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000458 Logger::CALLBACK_TAG, "set ", name, entry_point);
459}
460
461
462CpuProfiler::CpuProfiler()
463 : profiles_(new CpuProfilesCollection()),
464 next_profile_uid_(1),
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000465 token_enumerator_(new TokenEnumerator()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000466 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000467 processor_(NULL),
468 need_to_stop_sampler_(false),
469 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000470}
471
472
473CpuProfiler::~CpuProfiler() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000474 delete token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000475 delete profiles_;
476}
477
478
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000479void CpuProfiler::ResetProfiles() {
480 delete profiles_;
481 profiles_ = new CpuProfilesCollection();
482}
483
lrn@chromium.org25156de2010-04-06 13:10:27 +0000484void CpuProfiler::StartCollectingProfile(const char* title) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000485 if (profiles_->StartProfiling(title, next_profile_uid_++)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000486 StartProcessorIfNotStarted();
487 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000488 processor_->AddCurrentStack();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000489}
490
491
492void CpuProfiler::StartCollectingProfile(String* title) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000493 StartCollectingProfile(profiles_->GetName(title));
lrn@chromium.org25156de2010-04-06 13:10:27 +0000494}
495
496
497void CpuProfiler::StartProcessorIfNotStarted() {
498 if (processor_ == NULL) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000499 Isolate* isolate = Isolate::Current();
500
ager@chromium.org357bf652010-04-12 11:30:10 +0000501 // Disable logging when using the new implementation.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000502 saved_logging_nesting_ = isolate->logger()->logging_nesting_;
503 isolate->logger()->logging_nesting_ = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000504 generator_ = new ProfileGenerator(profiles_);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000505 processor_ = new ProfilerEventsProcessor(generator_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000506 NoBarrier_Store(&is_profiling_, true);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000507 processor_->Start();
508 // Enumerate stuff we already have in the heap.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000509 if (isolate->heap()->HasBeenSetup()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000510 if (!FLAG_prof_browser_mode) {
511 bool saved_log_code_flag = FLAG_log_code;
512 FLAG_log_code = true;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000513 isolate->logger()->LogCodeObjects();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000514 FLAG_log_code = saved_log_code_flag;
515 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000516 isolate->logger()->LogCompiledFunctions();
517 isolate->logger()->LogAccessorCallbacks();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000518 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000519 // Enable stack sampling.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000520 Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000521 if (!sampler->IsActive()) {
522 sampler->Start();
523 need_to_stop_sampler_ = true;
524 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000525 sampler->IncreaseProfilingDepth();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000526 }
527}
528
529
530CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000531 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000532 StopProcessorIfLastProfile(title);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000533 CpuProfile* result =
534 profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
535 title,
536 actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000537 if (result != NULL) {
538 result->Print();
539 }
540 return result;
541}
542
543
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000544CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
545 String* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000546 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000547 const char* profile_title = profiles_->GetName(title);
548 StopProcessorIfLastProfile(profile_title);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000549 int token = token_enumerator_->GetTokenId(security_token);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000550 return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000551}
552
553
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000554void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000555 if (profiles_->IsLastProfile(title)) StopProcessor();
556}
557
558
559void CpuProfiler::StopProcessor() {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000560 Logger* logger = Isolate::Current()->logger();
561 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000562 sampler->DecreaseProfilingDepth();
563 if (need_to_stop_sampler_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000564 sampler->Stop();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000565 need_to_stop_sampler_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000566 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000567 processor_->Stop();
568 processor_->Join();
569 delete processor_;
570 delete generator_;
571 processor_ = NULL;
572 NoBarrier_Store(&is_profiling_, false);
573 generator_ = NULL;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000574 logger->logging_nesting_ = saved_logging_nesting_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000575}
576
577} } // namespace v8::internal
578
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000579#endif // ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +0000580
581namespace v8 {
582namespace internal {
583
584void CpuProfiler::Setup() {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000585#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000586 Isolate* isolate = Isolate::Current();
587 if (isolate->cpu_profiler() == NULL) {
588 isolate->set_cpu_profiler(new CpuProfiler());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000589 }
590#endif
591}
592
593
594void CpuProfiler::TearDown() {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000595#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000596 Isolate* isolate = Isolate::Current();
597 if (isolate->cpu_profiler() != NULL) {
598 delete isolate->cpu_profiler();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000599 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000600 isolate->set_cpu_profiler(NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000601#endif
602}
603
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000604} } // namespace v8::internal