blob: 456770b4c67c122e0db54063431ee7e22dd4eee9 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Block6ded16b2010-05-10 14:33:55 +01004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Block6ded16b2010-05-10 14:33:55 +01006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/cpu-profiler-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +01008
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler.h"
10#include "src/frames-inl.h"
11#include "src/hashmap.h"
12#include "src/log-inl.h"
13#include "src/vm-state-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +010014
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "include/v8-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010016
17namespace v8 {
18namespace internal {
19
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020static const int kProfilerStackSize = 64 * KB;
Steve Block6ded16b2010-05-10 14:33:55 +010021
22
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator,
24 Sampler* sampler,
25 base::TimeDelta period)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010026 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
Steve Block9fac8402011-05-12 15:51:54 +010027 generator_(generator),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 sampler_(sampler),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040029 running_(1),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030 period_(period),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031 last_code_event_id_(0),
32 last_processed_code_event_id_(0) {}
Steve Block6ded16b2010-05-10 14:33:55 +010033
34
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
36 event.generic.order = ++last_code_event_id_;
37 events_buffer_.Enqueue(event);
Steve Block6ded16b2010-05-10 14:33:55 +010038}
39
40
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041void ProfilerEventsProcessor::AddCurrentStack(Isolate* isolate) {
42 TickSampleEventRecord record(last_code_event_id_);
43 RegisterState regs;
44 StackFrameIterator it(isolate);
45 if (!it.done()) {
46 StackFrame* frame = it.frame();
47 regs.sp = frame->sp();
48 regs.fp = frame->fp();
49 regs.pc = frame->pc();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010050 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051 record.sample.Init(isolate, regs, TickSample::kSkipCEntryFrame);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010052 ticks_from_vm_buffer_.Enqueue(record);
53}
54
55
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056void ProfilerEventsProcessor::StopSynchronously() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057 if (!base::NoBarrier_AtomicExchange(&running_, 0)) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 Join();
59}
60
61
62bool ProfilerEventsProcessor::ProcessCodeEvent() {
63 CodeEventsContainer record;
64 if (events_buffer_.Dequeue(&record)) {
Steve Block6ded16b2010-05-10 14:33:55 +010065 switch (record.generic.type) {
66#define PROFILER_TYPE_CASE(type, clss) \
67 case CodeEventRecord::type: \
68 record.clss##_.UpdateCodeMap(generator_->code_map()); \
69 break;
70
71 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
72
73#undef PROFILER_TYPE_CASE
74 default: return true; // Skip record.
75 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076 last_processed_code_event_id_ = record.generic.order;
Steve Block6ded16b2010-05-10 14:33:55 +010077 return true;
78 }
79 return false;
80}
81
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082ProfilerEventsProcessor::SampleProcessingResult
83 ProfilerEventsProcessor::ProcessOneSample() {
84 if (!ticks_from_vm_buffer_.IsEmpty()
85 && ticks_from_vm_buffer_.Peek()->order ==
86 last_processed_code_event_id_) {
87 TickSampleEventRecord record;
88 ticks_from_vm_buffer_.Dequeue(&record);
89 generator_->RecordTickSample(record.sample);
90 return OneSampleProcessed;
Steve Block6ded16b2010-05-10 14:33:55 +010091 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092
93 const TickSampleEventRecord* record = ticks_buffer_.Peek();
94 if (record == NULL) {
95 if (ticks_from_vm_buffer_.IsEmpty()) return NoSamplesInQueue;
96 return FoundSampleForNextCodeEvent;
97 }
98 if (record->order != last_processed_code_event_id_) {
99 return FoundSampleForNextCodeEvent;
100 }
101 generator_->RecordTickSample(record->sample);
102 ticks_buffer_.Remove();
103 return OneSampleProcessed;
Steve Block6ded16b2010-05-10 14:33:55 +0100104}
105
106
107void ProfilerEventsProcessor::Run() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108 while (!!base::NoBarrier_Load(&running_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 base::ElapsedTimer timer;
110 timer.Start();
111 // Keep processing existing events until we need to do next sample.
112 do {
113 if (FoundSampleForNextCodeEvent == ProcessOneSample()) {
114 // All ticks of the current last_processed_code_event_id_ are
115 // processed, proceed to the next code event.
116 ProcessCodeEvent();
117 }
118 } while (!timer.HasExpired(period_));
119
120 // Schedule next sample. sampler_ is NULL in tests.
121 if (sampler_) sampler_->DoSample();
Steve Block6ded16b2010-05-10 14:33:55 +0100122 }
123
124 // Process remaining tick events.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 do {
126 SampleProcessingResult result;
127 do {
128 result = ProcessOneSample();
129 } while (result == OneSampleProcessed);
130 } while (ProcessCodeEvent());
Steve Block6ded16b2010-05-10 14:33:55 +0100131}
132
133
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134void* ProfilerEventsProcessor::operator new(size_t size) {
135 return AlignedAlloc(size, V8_ALIGNOF(ProfilerEventsProcessor));
Steve Block6ded16b2010-05-10 14:33:55 +0100136}
137
138
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139void ProfilerEventsProcessor::operator delete(void* ptr) {
140 AlignedFree(ptr);
Steve Block6ded16b2010-05-10 14:33:55 +0100141}
142
143
144int CpuProfiler::GetProfilesCount() {
Leon Clarkef7060e22010-06-03 12:02:55 +0100145 // The count of profiles doesn't depend on a security token.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 return profiles_->profiles()->length();
Steve Block6ded16b2010-05-10 14:33:55 +0100147}
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150CpuProfile* CpuProfiler::GetProfile(int index) {
151 return profiles_->profiles()->at(index);
Steve Block6ded16b2010-05-10 14:33:55 +0100152}
153
154
Steve Block44f0eee2011-05-26 01:26:41 +0100155void CpuProfiler::DeleteAllProfiles() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156 if (is_profiling_) StopProcessor();
157 ResetProfiles();
Steve Block44f0eee2011-05-26 01:26:41 +0100158}
159
160
161void CpuProfiler::DeleteProfile(CpuProfile* profile) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 profiles_->RemoveProfile(profile);
Steve Block44f0eee2011-05-26 01:26:41 +0100163 delete profile;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 if (profiles_->profiles()->is_empty() && !is_profiling_) {
165 // If this was the last profile, clean up all accessory data as well.
166 ResetProfiles();
167 }
Steve Block44f0eee2011-05-26 01:26:41 +0100168}
169
170
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
172 return FLAG_prof_browser_mode
173 && (tag != Logger::CALLBACK_TAG
174 && tag != Logger::FUNCTION_TAG
175 && tag != Logger::LAZY_COMPILE_TAG
176 && tag != Logger::REG_EXP_TAG
177 && tag != Logger::SCRIPT_TAG);
Steve Block44f0eee2011-05-26 01:26:41 +0100178}
179
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
182 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
183 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
184 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
185 rec->start = entry_point;
186 rec->entry = profiles_->NewCodeEntry(
187 Logger::CALLBACK_TAG,
188 profiles_->GetName(name));
189 rec->size = 1;
190 rec->shared = NULL;
191 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100192}
193
194
195void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100196 Code* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 const char* name) {
198 if (FilterOutCodeCreateEvent(tag)) return;
199 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
200 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
201 rec->start = code->address();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202 rec->entry = profiles_->NewCodeEntry(
203 tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
204 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
205 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 rec->size = code->ExecutableSize();
207 rec->shared = NULL;
208 processor_->Enqueue(evt_rec);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100209}
210
211
212void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
213 Code* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 Name* name) {
215 if (FilterOutCodeCreateEvent(tag)) return;
216 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
217 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
218 rec->start = code->address();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 rec->entry = profiles_->NewCodeEntry(
220 tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
221 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
222 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000223 rec->size = code->ExecutableSize();
224 rec->shared = NULL;
225 processor_->Enqueue(evt_rec);
226}
227
228
229void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100230 SharedFunctionInfo* shared,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 CompilationInfo* info, Name* script_name) {
232 if (FilterOutCodeCreateEvent(tag)) return;
233 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
234 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
235 rec->start = code->address();
236 rec->entry = profiles_->NewCodeEntry(
237 tag, profiles_->GetFunctionName(shared->DebugName()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238 CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name),
239 CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
240 NULL, code->instruction_start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 if (info) {
242 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
243 }
244 if (shared->script()->IsScript()) {
245 DCHECK(Script::cast(shared->script()));
246 Script* script = Script::cast(shared->script());
247 rec->entry->set_script_id(script->id()->value());
248 rec->entry->set_bailout_reason(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400249 GetBailoutReason(shared->disable_optimization_reason()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250 }
251 rec->size = code->ExecutableSize();
252 rec->shared = shared->address();
253 processor_->Enqueue(evt_rec);
254}
255
256
257void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
258 SharedFunctionInfo* shared,
259 CompilationInfo* info, Name* script_name,
260 int line, int column) {
261 if (FilterOutCodeCreateEvent(tag)) return;
262 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
263 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
264 rec->start = code->address();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400265 Script* script = Script::cast(shared->script());
266 JITLineInfoTable* line_table = NULL;
267 if (script) {
268 line_table = new JITLineInfoTable();
269 for (RelocIterator it(code); !it.done(); it.next()) {
270 RelocInfo::Mode mode = it.rinfo()->rmode();
271 if (RelocInfo::IsPosition(mode)) {
272 int position = static_cast<int>(it.rinfo()->data());
273 if (position >= 0) {
274 int pc_offset = static_cast<int>(it.rinfo()->pc() - code->address());
275 int line_number = script->GetLineNumber(position);
276 line_table->SetPosition(pc_offset, line_number + 1);
277 }
278 }
279 }
280 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 rec->entry = profiles_->NewCodeEntry(
282 tag, profiles_->GetFunctionName(shared->DebugName()),
283 CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), line,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400284 column, line_table, code->instruction_start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 if (info) {
286 rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
287 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288 rec->entry->set_script_id(script->id()->value());
289 rec->size = code->ExecutableSize();
290 rec->shared = shared->address();
291 rec->entry->set_bailout_reason(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400292 GetBailoutReason(shared->disable_optimization_reason()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100294}
295
296
297void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 Code* code,
299 int args_count) {
300 if (FilterOutCodeCreateEvent(tag)) return;
301 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
302 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
303 rec->start = code->address();
304 rec->entry = profiles_->NewCodeEntry(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400305 tag, profiles_->GetName(args_count), "args_count: ",
306 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
307 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 rec->size = code->ExecutableSize();
309 rec->shared = NULL;
310 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100311}
312
313
314void CpuProfiler::CodeMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
316 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
317 rec->from = from;
318 rec->to = to;
319 processor_->Enqueue(evt_rec);
320}
321
322
323void CpuProfiler::CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
324 CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
325 CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
326 rec->start = code->address();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400327 rec->bailout_reason = GetBailoutReason(shared->disable_optimization_reason());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100329}
330
331
332void CpuProfiler::CodeDeleteEvent(Address from) {
Steve Block6ded16b2010-05-10 14:33:55 +0100333}
334
335
Steve Block44f0eee2011-05-26 01:26:41 +0100336void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 CodeEventsContainer evt_rec(CodeEventRecord::SHARED_FUNC_MOVE);
338 SharedFunctionInfoMoveEventRecord* rec =
339 &evt_rec.SharedFunctionInfoMoveEventRecord_;
340 rec->from = from;
341 rec->to = to;
342 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100343}
344
345
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
347 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
348 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
349 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
350 rec->start = entry_point;
351 rec->entry = profiles_->NewCodeEntry(
352 Logger::CALLBACK_TAG,
353 profiles_->GetName(name),
354 "get ");
355 rec->size = 1;
356 rec->shared = NULL;
357 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100358}
359
360
361void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 if (FilterOutCodeCreateEvent(Logger::REG_EXP_TAG)) return;
363 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
364 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
365 rec->start = code->address();
366 rec->entry = profiles_->NewCodeEntry(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400367 Logger::REG_EXP_TAG, profiles_->GetName(source), "RegExp: ",
368 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
369 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370 rec->size = code->ExecutableSize();
371 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100372}
373
374
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
376 if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
377 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
378 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
379 rec->start = entry_point;
380 rec->entry = profiles_->NewCodeEntry(
381 Logger::CALLBACK_TAG,
382 profiles_->GetName(name),
383 "set ");
384 rec->size = 1;
385 rec->shared = NULL;
386 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100387}
388
389
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390CpuProfiler::CpuProfiler(Isolate* isolate)
391 : isolate_(isolate),
392 sampling_interval_(base::TimeDelta::FromMicroseconds(
393 FLAG_cpu_profiler_sampling_interval)),
394 profiles_(new CpuProfilesCollection(isolate->heap())),
Steve Block6ded16b2010-05-10 14:33:55 +0100395 generator_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +0100396 processor_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 is_profiling_(false) {
398}
399
400
401CpuProfiler::CpuProfiler(Isolate* isolate,
402 CpuProfilesCollection* test_profiles,
403 ProfileGenerator* test_generator,
404 ProfilerEventsProcessor* test_processor)
405 : isolate_(isolate),
406 sampling_interval_(base::TimeDelta::FromMicroseconds(
407 FLAG_cpu_profiler_sampling_interval)),
408 profiles_(test_profiles),
409 generator_(test_generator),
410 processor_(test_processor),
Steve Block44f0eee2011-05-26 01:26:41 +0100411 is_profiling_(false) {
Steve Block6ded16b2010-05-10 14:33:55 +0100412}
413
414
415CpuProfiler::~CpuProfiler() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416 DCHECK(!is_profiling_);
Steve Block6ded16b2010-05-10 14:33:55 +0100417 delete profiles_;
418}
419
420
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421void CpuProfiler::set_sampling_interval(base::TimeDelta value) {
422 DCHECK(!is_profiling_);
423 sampling_interval_ = value;
424}
425
426
Steve Block44f0eee2011-05-26 01:26:41 +0100427void CpuProfiler::ResetProfiles() {
428 delete profiles_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 profiles_ = new CpuProfilesCollection(isolate()->heap());
Steve Block44f0eee2011-05-26 01:26:41 +0100430}
431
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432
433void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
434 if (profiles_->StartProfiling(title, record_samples)) {
Steve Block6ded16b2010-05-10 14:33:55 +0100435 StartProcessorIfNotStarted();
436 }
437}
438
439
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440void CpuProfiler::StartProfiling(String* title, bool record_samples) {
441 StartProfiling(profiles_->GetName(title), record_samples);
Steve Block6ded16b2010-05-10 14:33:55 +0100442}
443
444
445void CpuProfiler::StartProcessorIfNotStarted() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 if (processor_ != NULL) {
447 processor_->AddCurrentStack(isolate_);
448 return;
Steve Block6ded16b2010-05-10 14:33:55 +0100449 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450 Logger* logger = isolate_->logger();
451 // Disable logging when using the new implementation.
452 saved_is_logging_ = logger->is_logging_;
453 logger->is_logging_ = false;
454 generator_ = new ProfileGenerator(profiles_);
455 Sampler* sampler = logger->sampler();
456 processor_ = new ProfilerEventsProcessor(
457 generator_, sampler, sampling_interval_);
458 is_profiling_ = true;
459 // Enumerate stuff we already have in the heap.
460 DCHECK(isolate_->heap()->HasBeenSetUp());
461 if (!FLAG_prof_browser_mode) {
462 logger->LogCodeObjects();
463 }
464 logger->LogCompiledFunctions();
465 logger->LogAccessorCallbacks();
466 LogBuiltins();
467 // Enable stack sampling.
468 sampler->SetHasProcessingThread(true);
469 sampler->IncreaseProfilingDepth();
470 processor_->AddCurrentStack(isolate_);
471 processor_->StartSynchronously();
Steve Block6ded16b2010-05-10 14:33:55 +0100472}
473
474
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475CpuProfile* CpuProfiler::StopProfiling(const char* title) {
476 if (!is_profiling_) return NULL;
Iain Merrick75681382010-08-19 15:07:18 +0100477 StopProcessorIfLastProfile(title);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 CpuProfile* result = profiles_->StopProfiling(title);
Steve Block6ded16b2010-05-10 14:33:55 +0100479 if (result != NULL) {
480 result->Print();
481 }
482 return result;
483}
484
485
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486CpuProfile* CpuProfiler::StopProfiling(String* title) {
487 if (!is_profiling_) return NULL;
Iain Merrick75681382010-08-19 15:07:18 +0100488 const char* profile_title = profiles_->GetName(title);
489 StopProcessorIfLastProfile(profile_title);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 return profiles_->StopProfiling(profile_title);
Steve Block6ded16b2010-05-10 14:33:55 +0100491}
492
493
Iain Merrick75681382010-08-19 15:07:18 +0100494void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
Steve Block44f0eee2011-05-26 01:26:41 +0100495 if (profiles_->IsLastProfile(title)) StopProcessor();
496}
497
498
499void CpuProfiler::StopProcessor() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 Logger* logger = isolate_->logger();
Steve Block44f0eee2011-05-26 01:26:41 +0100501 Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502 is_profiling_ = false;
503 processor_->StopSynchronously();
Steve Block44f0eee2011-05-26 01:26:41 +0100504 delete processor_;
505 delete generator_;
506 processor_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +0100507 generator_ = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 sampler->SetHasProcessingThread(false);
509 sampler->DecreaseProfilingDepth();
510 logger->is_logging_ = saved_is_logging_;
Steve Block6ded16b2010-05-10 14:33:55 +0100511}
512
Steve Block6ded16b2010-05-10 14:33:55 +0100513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514void CpuProfiler::LogBuiltins() {
515 Builtins* builtins = isolate_->builtins();
516 DCHECK(builtins->is_initialized());
517 for (int i = 0; i < Builtins::builtin_count; i++) {
518 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
519 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
520 Builtins::Name id = static_cast<Builtins::Name>(i);
521 rec->start = builtins->builtin(id)->address();
522 rec->builtin_id = id;
523 processor_->Enqueue(evt_rec);
Steve Block6ded16b2010-05-10 14:33:55 +0100524 }
Steve Block6ded16b2010-05-10 14:33:55 +0100525}
526
527
Steve Block6ded16b2010-05-10 14:33:55 +0100528} } // namespace v8::internal