blob: 109ddd5d976f0a36ccdb1512e02b2a78467238d6 [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
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000032#include "compiler.h"
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +000033#include "frames-inl.h"
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000034#include "hashmap.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000035#include "log-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "vm-state-inl.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000037
ager@chromium.org357bf652010-04-12 11:30:10 +000038#include "../include/v8-profiler.h"
39
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000040namespace v8 {
41namespace internal {
42
mmassi@chromium.org49a44672012-12-04 13:52:03 +000043static 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
danno@chromium.orgca29dd82013-04-26 11:59:48 +000048ProfilerEventsProcessor::ProfilerEventsProcessor(
49 ProfileGenerator* generator, CpuProfilesCollection* profiles)
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000050 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
lrn@chromium.org5d00b602011-01-05 09:51:43 +000051 generator_(generator),
danno@chromium.orgca29dd82013-04-26 11:59:48 +000052 profiles_(profiles),
erik.corry@gmail.com145eff52010-08-23 11:36:18 +000053 running_(true),
mmassi@chromium.org49a44672012-12-04 13:52:03 +000054 ticks_buffer_(sizeof(TickSampleEventRecord),
55 kTickSamplesBufferChunkSize,
ulan@chromium.org750145a2013-03-07 15:14:13 +000056 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,
ulan@chromium.org750145a2013-03-07 15:14:13 +000063 Name* name,
lrn@chromium.org25156de2010-04-06 13:10:27 +000064 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;
danno@chromium.orgca29dd82013-04-26 11:59:48 +000071 rec->entry = profiles_->NewCodeEntry(tag, prefix, name);
lrn@chromium.org25156de2010-04-06 13:10:27 +000072 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,
ulan@chromium.org750145a2013-03-07 15:14:13 +000079 Name* name,
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000080 String* resource_name,
81 int line_number,
82 Address start,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000083 unsigned size,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000084 Address shared,
85 CompilationInfo* info) {
ager@chromium.org357bf652010-04-12 11:30:10 +000086 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000087 CodeEventsContainer evt_rec;
88 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
89 rec->type = CodeEventRecord::CODE_CREATION;
90 rec->order = ++enqueue_order_;
91 rec->start = start;
danno@chromium.orgca29dd82013-04-26 11:59:48 +000092 rec->entry = profiles_->NewCodeEntry(tag, name, resource_name, line_number);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000093 if (info) {
94 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
95 }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000096 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000097 rec->shared = shared;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000098 events_buffer_.Enqueue(evt_rec);
99}
100
101
102void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
103 const char* name,
104 Address start,
105 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000106 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000107 CodeEventsContainer evt_rec;
108 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
109 rec->type = CodeEventRecord::CODE_CREATION;
110 rec->order = ++enqueue_order_;
111 rec->start = start;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000112 rec->entry = profiles_->NewCodeEntry(tag, name);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000113 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000114 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000115 events_buffer_.Enqueue(evt_rec);
116}
117
118
119void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
120 int args_count,
121 Address start,
122 unsigned size) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000123 if (FilterOutCodeCreateEvent(tag)) return;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000124 CodeEventsContainer evt_rec;
125 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
126 rec->type = CodeEventRecord::CODE_CREATION;
127 rec->order = ++enqueue_order_;
128 rec->start = start;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000129 rec->entry = profiles_->NewCodeEntry(tag, args_count);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000130 rec->size = size;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000131 rec->shared = NULL;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000132 events_buffer_.Enqueue(evt_rec);
133}
134
135
136void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
137 CodeEventsContainer evt_rec;
138 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
139 rec->type = CodeEventRecord::CODE_MOVE;
140 rec->order = ++enqueue_order_;
141 rec->from = from;
142 rec->to = to;
143 events_buffer_.Enqueue(evt_rec);
144}
145
146
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000147void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
148 Address to) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000149 CodeEventsContainer evt_rec;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000150 SharedFunctionInfoMoveEventRecord* rec =
151 &evt_rec.SharedFunctionInfoMoveEventRecord_;
152 rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000153 rec->order = ++enqueue_order_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000154 rec->from = from;
155 rec->to = to;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000156 events_buffer_.Enqueue(evt_rec);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000157}
158
159
ager@chromium.org357bf652010-04-12 11:30:10 +0000160void ProfilerEventsProcessor::RegExpCodeCreateEvent(
161 Logger::LogEventsAndTags tag,
162 const char* prefix,
163 String* name,
164 Address start,
165 unsigned size) {
166 if (FilterOutCodeCreateEvent(tag)) return;
167 CodeEventsContainer evt_rec;
168 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
169 rec->type = CodeEventRecord::CODE_CREATION;
170 rec->order = ++enqueue_order_;
171 rec->start = start;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000172 rec->entry = profiles_->NewCodeEntry(tag, prefix, name);
ager@chromium.org357bf652010-04-12 11:30:10 +0000173 rec->size = size;
174 events_buffer_.Enqueue(evt_rec);
175}
176
177
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000178void ProfilerEventsProcessor::AddCurrentStack() {
ager@chromium.org04921a82011-06-27 13:21:41 +0000179 TickSampleEventRecord record(enqueue_order_);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000180 TickSample* sample = &record.sample;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000181 Isolate* isolate = Isolate::Current();
182 sample->state = isolate->current_vm_state();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000183 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000184 for (StackTraceFrameIterator it(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000185 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
186 it.Advance()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000187 sample->stack[sample->frames_count++] = it.frame()->pc();
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000188 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000189 ticks_from_vm_buffer_.Enqueue(record);
190}
191
192
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000193bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000194 CodeEventsContainer record;
195 if (events_buffer_.Dequeue(&record)) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000196 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
247void ProfilerEventsProcessor::Run() {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000248 unsigned dequeue_order = 0;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000249
250 while (running_) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000251 // Process ticks until we have any.
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);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000256 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000257 YieldCPU();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000258 }
259
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000260 // Process remaining tick events.
261 ticks_buffer_.FlushResidualRecords();
262 // Perform processing until we have tick events, skip remaining code events.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000263 while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000264}
265
266
lrn@chromium.org25156de2010-04-06 13:10:27 +0000267int CpuProfiler::GetProfilesCount() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000268 // The count of profiles doesn't depend on a security token.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000269 return profiles_->Profiles(TokenEnumerator::kNoSecurityToken)->length();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000270}
271
272
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000273CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000274 const int token = token_enumerator_->GetTokenId(security_token);
275 return profiles_->Profiles(token)->at(index);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000276}
277
278
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000279CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000280 const int token = token_enumerator_->GetTokenId(security_token);
281 return profiles_->GetProfile(token, uid);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000282}
283
284
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000285TickSample* CpuProfiler::TickSampleEvent() {
286 if (is_profiling_) return processor_->TickSampleEvent();
287 return NULL;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000288}
289
290
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000291void CpuProfiler::DeleteAllProfiles() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000292 if (is_profiling_) StopProcessor();
293 ResetProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000294}
295
296
297void CpuProfiler::DeleteProfile(CpuProfile* profile) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000298 profiles_->RemoveProfile(profile);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 delete profile;
300}
301
302
303bool CpuProfiler::HasDetachedProfiles() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000304 return profiles_->HasDetachedProfiles();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000305}
306
307
ulan@chromium.org750145a2013-03-07 15:14:13 +0000308void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000309 processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000310 Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
311}
312
313
314void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
315 Code* code, const char* comment) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000316 processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000317 tag, comment, code->address(), code->ExecutableSize());
318}
319
320
321void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000322 Code* code, Name* name) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000323 processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000324 tag,
325 name,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000326 isolate_->heap()->empty_string(),
ager@chromium.org357bf652010-04-12 11:30:10 +0000327 v8::CpuProfileNode::kNoLineNumberInfo,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000328 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000329 code->ExecutableSize(),
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000330 NULL,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000331 NULL);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000332}
333
334
335void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000336 Code* code,
337 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000338 CompilationInfo* info,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000339 Name* name) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000340 processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000341 tag,
342 name,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000343 isolate_->heap()->empty_string(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000344 v8::CpuProfileNode::kNoLineNumberInfo,
345 code->address(),
346 code->ExecutableSize(),
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000347 shared->address(),
348 info);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000349}
350
351
352void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
353 Code* code,
354 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000355 CompilationInfo* info,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000356 String* source, int line) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000357 processor_->CodeCreateEvent(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000358 tag,
359 shared->DebugName(),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000360 source,
361 line,
362 code->address(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000363 code->ExecutableSize(),
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000364 shared->address(),
365 info);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000366}
367
368
369void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
370 Code* code, int args_count) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000371 processor_->CodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000372 tag,
373 args_count,
374 code->address(),
375 code->ExecutableSize());
376}
377
378
379void CpuProfiler::CodeMoveEvent(Address from, Address to) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000380 processor_->CodeMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000381}
382
383
384void CpuProfiler::CodeDeleteEvent(Address from) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000385}
386
387
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000388void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000389 processor_->SharedFunctionInfoMoveEvent(from, to);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000390}
391
392
ulan@chromium.org750145a2013-03-07 15:14:13 +0000393void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000394 processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000395 Logger::CALLBACK_TAG, "get ", name, entry_point);
396}
397
398
399void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000400 processor_->RegExpCodeCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000401 Logger::REG_EXP_TAG,
ager@chromium.org357bf652010-04-12 11:30:10 +0000402 "RegExp: ",
lrn@chromium.org25156de2010-04-06 13:10:27 +0000403 source,
lrn@chromium.org25156de2010-04-06 13:10:27 +0000404 code->address(),
405 code->ExecutableSize());
406}
407
408
ulan@chromium.org750145a2013-03-07 15:14:13 +0000409void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000410 processor_->CallbackCreateEvent(
lrn@chromium.org25156de2010-04-06 13:10:27 +0000411 Logger::CALLBACK_TAG, "set ", name, entry_point);
412}
413
414
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000415CpuProfiler::CpuProfiler(Isolate* isolate)
416 : isolate_(isolate),
417 profiles_(new CpuProfilesCollection()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000418 next_profile_uid_(1),
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000419 token_enumerator_(new TokenEnumerator()),
lrn@chromium.org25156de2010-04-06 13:10:27 +0000420 generator_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000421 processor_(NULL),
422 need_to_stop_sampler_(false),
423 is_profiling_(false) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000424}
425
426
427CpuProfiler::~CpuProfiler() {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000428 delete token_enumerator_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000429 delete profiles_;
430}
431
432
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000433void CpuProfiler::ResetProfiles() {
434 delete profiles_;
435 profiles_ = new CpuProfilesCollection();
436}
437
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000438void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
439 if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
lrn@chromium.org25156de2010-04-06 13:10:27 +0000440 StartProcessorIfNotStarted();
441 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000442 processor_->AddCurrentStack();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000443}
444
445
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000446void CpuProfiler::StartProfiling(String* title, bool record_samples) {
447 StartProfiling(profiles_->GetName(title), record_samples);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000448}
449
450
451void CpuProfiler::StartProcessorIfNotStarted() {
452 if (processor_ == NULL) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000453 // Disable logging when using the new implementation.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000454 saved_logging_nesting_ = isolate_->logger()->logging_nesting_;
455 isolate_->logger()->logging_nesting_ = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000456 generator_ = new ProfileGenerator(profiles_);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000457 processor_ = new ProfilerEventsProcessor(generator_, profiles_);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000458 is_profiling_ = true;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000459 processor_->StartSynchronously();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000460 // Enumerate stuff we already have in the heap.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000461 if (isolate_->heap()->HasBeenSetUp()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000462 if (!FLAG_prof_browser_mode) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000463 isolate_->logger()->LogCodeObjects();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000464 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000465 isolate_->logger()->LogCompiledFunctions();
466 isolate_->logger()->LogAccessorCallbacks();
lrn@chromium.org25156de2010-04-06 13:10:27 +0000467 }
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000468 // Enable stack sampling.
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000469 Sampler* sampler = isolate_->logger()->sampler();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000470 sampler->IncreaseProfilingDepth();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000471 if (!sampler->IsActive()) {
472 sampler->Start();
473 need_to_stop_sampler_ = true;
474 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000475 }
476}
477
478
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000479CpuProfile* CpuProfiler::StopProfiling(const char* title) {
480 if (!is_profiling_) return NULL;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000481 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000482 StopProcessorIfLastProfile(title);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000483 CpuProfile* result =
484 profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
485 title,
486 actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000487 if (result != NULL) {
488 result->Print();
489 }
490 return result;
491}
492
493
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000494CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
495 if (!is_profiling_) return NULL;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000496 const double actual_sampling_rate = generator_->actual_sampling_rate();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000497 const char* profile_title = profiles_->GetName(title);
498 StopProcessorIfLastProfile(profile_title);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000499 int token = token_enumerator_->GetTokenId(security_token);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000500 return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000501}
502
503
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000504void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000505 if (profiles_->IsLastProfile(title)) StopProcessor();
506}
507
508
509void CpuProfiler::StopProcessor() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000510 Logger* logger = isolate_->logger();
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000511 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000512 sampler->DecreaseProfilingDepth();
513 if (need_to_stop_sampler_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514 sampler->Stop();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000515 need_to_stop_sampler_ = false;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000516 }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000517 is_profiling_ = false;
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000518 processor_->Stop();
519 processor_->Join();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000520 delete processor_;
521 delete generator_;
522 processor_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000523 generator_ = NULL;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000524 logger->logging_nesting_ = saved_logging_nesting_;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000525}
526
lrn@chromium.org25156de2010-04-06 13:10:27 +0000527
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000528} } // namespace v8::internal