blob: 3d5e697861951ecd8467f4ff1f7f13b3f7914911 [file] [log] [blame]
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +00001// Copyright 2012 the V8 project authors. All rights reserved.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "cpu-profiler-inl.h"
31
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000032#include "frames-inl.h"
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000033#include "hashmap.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000034#include "log-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000035#include "vm-state-inl.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000036
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
mmassi@chromium.org49a44672012-12-04 13:52:03 +000042static const int kEventsBufferSize = 256 * KB;
43static const int kTickSamplesBufferChunkSize = 64 * KB;
44static const int kTickSamplesBufferChunksCount = 16;
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000045static const int kProfilerStackSize = 64 * KB;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000046
47
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000048ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator,
49 Sampler* sampler,
50 int period_in_useconds)
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000051 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
lrn@chromium.org5d00b602011-01-05 09:51:43 +000052 generator_(generator),
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000053 sampler_(sampler),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000054 running_(true),
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000055 period_in_useconds_(period_in_useconds),
mmassi@chromium.org49a44672012-12-04 13:52:03 +000056 ticks_buffer_(sizeof(TickSampleEventRecord),
57 kTickSamplesBufferChunkSize,
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000058 kTickSamplesBufferChunksCount,
59 !Sampler::CanSampleOnProfilerEventsProcessorThread()),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000060 enqueue_order_(0) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000061}
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000062
63
lrn@chromium.org25156de2010-04-06 13:10:27 +000064void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
65 const char* prefix,
66 String* name,
67 Address start) {
ager@chromium.org357bf652010-04-12 11:30:10 +000068 if (FilterOutCodeCreateEvent(tag)) return;
lrn@chromium.org25156de2010-04-06 13:10:27 +000069 CodeEventsContainer evt_rec;
70 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
71 rec->type = CodeEventRecord::CODE_CREATION;
72 rec->order = ++enqueue_order_;
73 rec->start = start;
74 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
75 rec->size = 1;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000076 rec->shared = NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +000077 events_buffer_.Enqueue(evt_rec);
78}
79
80
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000081void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
82 String* name,
83 String* resource_name,
84 int line_number,
85 Address start,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000086 unsigned size,
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000087 Address shared) {
ager@chromium.org357bf652010-04-12 11:30:10 +000088 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000089 CodeEventsContainer evt_rec;
90 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
91 rec->type = CodeEventRecord::CODE_CREATION;
92 rec->order = ++enqueue_order_;
93 rec->start = start;
94 rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
95 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000096 rec->shared = shared;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000097 events_buffer_.Enqueue(evt_rec);
98}
99
100
101void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
102 const char* name,
103 Address start,
104 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000105 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000106 CodeEventsContainer evt_rec;
107 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
108 rec->type = CodeEventRecord::CODE_CREATION;
109 rec->order = ++enqueue_order_;
110 rec->start = start;
111 rec->entry = generator_->NewCodeEntry(tag, name);
112 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000113 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000114 events_buffer_.Enqueue(evt_rec);
115}
116
117
118void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
119 int args_count,
120 Address start,
121 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000122 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000123 CodeEventsContainer evt_rec;
124 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
125 rec->type = CodeEventRecord::CODE_CREATION;
126 rec->order = ++enqueue_order_;
127 rec->start = start;
128 rec->entry = generator_->NewCodeEntry(tag, args_count);
129 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000130 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000131 events_buffer_.Enqueue(evt_rec);
132}
133
134
135void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
136 CodeEventsContainer evt_rec;
137 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
138 rec->type = CodeEventRecord::CODE_MOVE;
139 rec->order = ++enqueue_order_;
140 rec->from = from;
141 rec->to = to;
142 events_buffer_.Enqueue(evt_rec);
143}
144
145
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000146void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
147 Address to) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000148 CodeEventsContainer evt_rec;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000149 SharedFunctionInfoMoveEventRecord* rec =
150 &evt_rec.SharedFunctionInfoMoveEventRecord_;
151 rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000152 rec->order = ++enqueue_order_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000153 rec->from = from;
154 rec->to = to;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000155 events_buffer_.Enqueue(evt_rec);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000156}
157
158
ager@chromium.org357bf652010-04-12 11:30:10 +0000159void ProfilerEventsProcessor::RegExpCodeCreateEvent(
160 Logger::LogEventsAndTags tag,
161 const char* prefix,
162 String* name,
163 Address start,
164 unsigned size) {
165 if (FilterOutCodeCreateEvent(tag)) return;
166 CodeEventsContainer evt_rec;
167 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
168 rec->type = CodeEventRecord::CODE_CREATION;
169 rec->order = ++enqueue_order_;
170 rec->start = start;
171 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
172 rec->size = size;
173 events_buffer_.Enqueue(evt_rec);
174}
175
176
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000177void ProfilerEventsProcessor::AddCurrentStack() {
ager@chromium.org04921a82011-06-27 13:21:41 +0000178 TickSampleEventRecord record(enqueue_order_);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000179 TickSample* sample = &record.sample;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000180 Isolate* isolate = Isolate::Current();
181 sample->state = isolate->current_vm_state();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000182 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000183 for (StackTraceFrameIterator it(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000184 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
185 it.Advance()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000186 sample->stack[sample->frames_count++] = it.frame()->pc();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000187 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000188 ticks_from_vm_buffer_.Enqueue(record);
189}
190
191
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000192bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
193 if (!events_buffer_.IsEmpty()) {
194 CodeEventsContainer record;
195 events_buffer_.Dequeue(&record);
196 switch (record.generic.type) {
197#define PROFILER_TYPE_CASE(type, clss) \
198 case CodeEventRecord::type: \
199 record.clss##_.UpdateCodeMap(generator_->code_map()); \
200 break;
201
202 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
203
204#undef PROFILER_TYPE_CASE
205 default: return true; // Skip record.
206 }
207 *dequeue_order = record.generic.order;
208 return true;
209 }
210 return false;
211}
212
213
214bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
215 while (true) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000216 if (!ticks_from_vm_buffer_.IsEmpty()
217 && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
218 TickSampleEventRecord record;
219 ticks_from_vm_buffer_.Dequeue(&record);
220 generator_->RecordTickSample(record.sample);
221 }
222
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000223 const TickSampleEventRecord* rec =
224 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
225 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
226 // Make a local copy of tick sample record to ensure that it won't
227 // be modified as we are processing it. This is possible as the
228 // sampler writes w/o any sync to the queue, so if the processor
229 // will get far behind, a record may be modified right under its
230 // feet.
231 TickSampleEventRecord record = *rec;
232 if (record.order == dequeue_order) {
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000233 // A paranoid check to make sure that we don't get a memory overrun
234 // in case of frames_count having a wild value.
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000235 if (record.sample.frames_count < 0
236 || record.sample.frames_count > TickSample::kMaxFramesCount)
237 record.sample.frames_count = 0;
238 generator_->RecordTickSample(record.sample);
239 ticks_buffer_.FinishDequeue();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000240 } else {
241 return true;
242 }
243 }
244}
245
246
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000247void ProfilerEventsProcessor::ProcessEventsAndDoSample(
248 unsigned* dequeue_order) {
249 int64_t stop_time = OS::Ticks() + period_in_useconds_;
250 // Keep processing existing events until we need to do next sample.
251 while (OS::Ticks() < stop_time) {
252 if (ProcessTicks(*dequeue_order)) {
253 // All ticks of the current dequeue_order are processed,
254 // proceed to the next code event.
255 ProcessCodeEvent(dequeue_order);
256 }
257 }
258 // Schedule next sample. sampler_ is NULL in tests.
259 if (sampler_)
260 sampler_->DoSample();
261}
262
263
264void ProfilerEventsProcessor::ProcessEventsAndYield(unsigned* dequeue_order) {
265 if (ProcessTicks(*dequeue_order)) {
266 // All ticks of the current dequeue_order are processed,
267 // proceed to the next code event.
268 ProcessCodeEvent(dequeue_order);
269 }
270 YieldCPU();
271}
272
273
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000274void ProfilerEventsProcessor::Run() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000275 unsigned dequeue_order = 0;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000276
277 while (running_) {
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000278 if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
279 ProcessEventsAndDoSample(&dequeue_order);
280 } else {
281 ProcessEventsAndYield(&dequeue_order);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000282 }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000283 }
284
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000285 // Process remaining tick events.
286 ticks_buffer_.FlushResidualRecords();
287 // Perform processing until we have tick events, skip remaining code events.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000288 while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000289}
290
291
lrn@chromium.org25156de2010-04-06 13:10:27 +0000292void CpuProfiler::StartProfiling(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000293 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
294 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000295}
296
297
298void CpuProfiler::StartProfiling(String* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
300 Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000301}
302
303
304CpuProfile* CpuProfiler::StopProfiling(const char* title) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000305 Isolate* isolate = Isolate::Current();
306 return is_profiling(isolate) ?
307 isolate->cpu_profiler()->StopCollectingProfile(title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000308}
309
310
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000311CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000312 Isolate* isolate = Isolate::Current();
313 return is_profiling(isolate) ?
314 isolate->cpu_profiler()->StopCollectingProfile(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000315 security_token, title) : NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000316}
317
318
319int CpuProfiler::GetProfilesCount() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000320 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000321 // The count of profiles doesn't depend on a security token.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000322 return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000323 TokenEnumerator::kNoSecurityToken)->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000324}
325
326
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000327CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000328 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
329 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
330 const int token = profiler->token_enumerator_->GetTokenId(security_token);
331 return profiler->profiles_->Profiles(token)->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000332}
333
334
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000335CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000336 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
337 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
338 const int token = profiler->token_enumerator_->GetTokenId(security_token);
339 return profiler->profiles_->GetProfile(token, uid);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000340}
341
342
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000343TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000344 if (CpuProfiler::is_profiling(isolate)) {
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000345 return isolate->cpu_profiler()->processor_->TickSampleEvent();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000346 } else {
347 return NULL;
348 }
349}
350
351
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000352void CpuProfiler::DeleteAllProfiles() {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000353 Isolate* isolate = Isolate::Current();
354 ASSERT(isolate->cpu_profiler() != NULL);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000355 if (is_profiling(isolate)) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000356 isolate->cpu_profiler()->StopProcessor();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000357 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000358 isolate->cpu_profiler()->ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000359}
360
361
362void CpuProfiler::DeleteProfile(CpuProfile* profile) {
363 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
364 Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
365 delete profile;
366}
367
368
369bool CpuProfiler::HasDetachedProfiles() {
370 ASSERT(Isolate::Current()->cpu_profiler() != NULL);
371 return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
372}
373
374
lrn@chromium.org25156de2010-04-06 13:10:27 +0000375void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000376 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000377 Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
378}
379
380
381void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
382 Code* code, const char* comment) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000383 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000384 tag, comment, code->address(), code->ExecutableSize());
385}
386
387
388void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
389 Code* code, String* name) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000390 Isolate* isolate = Isolate::Current();
391 isolate->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000392 tag,
393 name,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000394 isolate->heap()->empty_string(),
ager@chromium.org357bf652010-04-12 11:30:10 +0000395 v8::CpuProfileNode::kNoLineNumberInfo,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000396 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000397 code->ExecutableSize(),
398 NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000399}
400
401
402void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000403 Code* code,
404 SharedFunctionInfo* shared,
405 String* name) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000406 Isolate* isolate = Isolate::Current();
407 isolate->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000408 tag,
409 name,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000410 isolate->heap()->empty_string(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000411 v8::CpuProfileNode::kNoLineNumberInfo,
412 code->address(),
413 code->ExecutableSize(),
414 shared->address());
415}
416
417
418void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
419 Code* code,
420 SharedFunctionInfo* shared,
421 String* source, int line) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000422 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000423 tag,
424 shared->DebugName(),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000425 source,
426 line,
427 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000428 code->ExecutableSize(),
429 shared->address());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000430}
431
432
433void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
434 Code* code, int args_count) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000435 Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000436 tag,
437 args_count,
438 code->address(),
439 code->ExecutableSize());
440}
441
442
443void CpuProfiler::CodeMoveEvent(Address from, Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000444 Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000445}
446
447
448void CpuProfiler::CodeDeleteEvent(Address from) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000449}
450
451
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000452void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000453 CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
454 profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000455}
456
457
458void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000459 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000460 Logger::CALLBACK_TAG, "get ", name, entry_point);
461}
462
463
464void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000465 Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000466 Logger::REG_EXP_TAG,
ager@chromium.org357bf652010-04-12 11:30:10 +0000467 "RegExp: ",
lrn@chromium.org25156de2010-04-06 13:10:27 +0000468 source,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000469 code->address(),
470 code->ExecutableSize());
471}
472
473
474void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000475 Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000476 Logger::CALLBACK_TAG, "set ", name, entry_point);
477}
478
479
480CpuProfiler::CpuProfiler()
481 : profiles_(new CpuProfilesCollection()),
482 next_profile_uid_(1),
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000483 token_enumerator_(new TokenEnumerator()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000484 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000485 processor_(NULL),
486 need_to_stop_sampler_(false),
487 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000488}
489
490
491CpuProfiler::~CpuProfiler() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000492 delete token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000493 delete profiles_;
494}
495
496
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000497void CpuProfiler::ResetProfiles() {
498 delete profiles_;
499 profiles_ = new CpuProfilesCollection();
500}
501
lrn@chromium.org25156de2010-04-06 13:10:27 +0000502void CpuProfiler::StartCollectingProfile(const char* title) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000503 if (profiles_->StartProfiling(title, next_profile_uid_++)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000504 StartProcessorIfNotStarted();
505 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000506 processor_->AddCurrentStack();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000507}
508
509
510void CpuProfiler::StartCollectingProfile(String* title) {
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000511 StartCollectingProfile(profiles_->GetName(title));
lrn@chromium.org25156de2010-04-06 13:10:27 +0000512}
513
514
515void CpuProfiler::StartProcessorIfNotStarted() {
516 if (processor_ == NULL) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000517 Isolate* isolate = Isolate::Current();
518
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000519 Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
ager@chromium.org357bf652010-04-12 11:30:10 +0000520 // Disable logging when using the new implementation.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000521 saved_logging_nesting_ = isolate->logger()->logging_nesting_;
522 isolate->logger()->logging_nesting_ = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000523 generator_ = new ProfileGenerator(profiles_);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000524 processor_ = new ProfilerEventsProcessor(generator_,
525 sampler,
526 FLAG_cpu_profiler_sampling_period);
527 is_profiling_ = true;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000528 // Enumerate stuff we already have in the heap.
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000529 if (isolate->heap()->HasBeenSetUp()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000530 if (!FLAG_prof_browser_mode) {
531 bool saved_log_code_flag = FLAG_log_code;
532 FLAG_log_code = true;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000533 isolate->logger()->LogCodeObjects();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000534 FLAG_log_code = saved_log_code_flag;
535 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000536 isolate->logger()->LogCompiledFunctions();
537 isolate->logger()->LogAccessorCallbacks();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000538 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000539 // Enable stack sampling.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000540 if (!sampler->IsActive()) {
541 sampler->Start();
542 need_to_stop_sampler_ = true;
543 }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000544 sampler->SetHasProcessingThread(true);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000545 sampler->IncreaseProfilingDepth();
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000546 processor_->Start();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000547 }
548}
549
550
551CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000552 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000553 StopProcessorIfLastProfile(title);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000554 CpuProfile* result =
555 profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
556 title,
557 actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000558 if (result != NULL) {
559 result->Print();
560 }
561 return result;
562}
563
564
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000565CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
566 String* title) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000567 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000568 const char* profile_title = profiles_->GetName(title);
569 StopProcessorIfLastProfile(profile_title);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000570 int token = token_enumerator_->GetTokenId(security_token);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000571 return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000572}
573
574
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000575void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000576 if (profiles_->IsLastProfile(title)) StopProcessor();
577}
578
579
580void CpuProfiler::StopProcessor() {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000581 Logger* logger = Isolate::Current()->logger();
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000582 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000583 sampler->DecreaseProfilingDepth();
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000584 sampler->SetHasProcessingThread(false);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000585 if (need_to_stop_sampler_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000586 sampler->Stop();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000587 need_to_stop_sampler_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000588 }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000589 is_profiling_ = false;
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000590 processor_->Stop();
591 processor_->Join();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000592 delete processor_;
593 delete generator_;
594 processor_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000595 generator_ = NULL;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000596 logger->logging_nesting_ = saved_logging_nesting_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000597}
598
lrn@chromium.org25156de2010-04-06 13:10:27 +0000599
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000600void CpuProfiler::SetUp() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000601 Isolate* isolate = Isolate::Current();
602 if (isolate->cpu_profiler() == NULL) {
603 isolate->set_cpu_profiler(new CpuProfiler());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000604 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000605}
606
607
608void CpuProfiler::TearDown() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000609 Isolate* isolate = Isolate::Current();
610 if (isolate->cpu_profiler() != NULL) {
611 delete isolate->cpu_profiler();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000612 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000613 isolate->set_cpu_profiler(NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000614}
615
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000616} } // namespace v8::internal