| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/profiler/cpu-profiler.h" | 5 #include "src/profiler/cpu-profiler.h" |
| 6 | 6 |
| 7 #include "src/debug/debug.h" | 7 #include "src/debug/debug.h" |
| 8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
| 9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
| 10 #include "src/locked-queue-inl.h" | 10 #include "src/locked-queue-inl.h" |
| 11 #include "src/log-inl.h" | 11 #include "src/log-inl.h" |
| 12 #include "src/profiler/cpu-profiler-inl.h" | 12 #include "src/profiler/cpu-profiler-inl.h" |
| 13 #include "src/vm-state-inl.h" | 13 #include "src/vm-state-inl.h" |
| 14 | 14 |
| 15 #include "include/v8-profiler.h" | 15 #include "include/v8-profiler.h" |
| 16 | 16 |
| 17 namespace v8 { | 17 namespace v8 { |
| 18 namespace internal { | 18 namespace internal { |
| 19 | 19 |
| 20 static const int kProfilerStackSize = 64 * KB; | 20 static const int kProfilerStackSize = 64 * KB; |
| 21 | 21 |
| 22 class CpuSampler : public sampler::Sampler { |
| 23 public: |
| 24 CpuSampler(Isolate* isolate, ProfilerEventsProcessor* processor) |
| 25 : sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)), |
| 26 processor_(processor) {} |
| 22 | 27 |
| 23 ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator, | 28 void SampleStack(const v8::RegisterState& state) override { |
| 24 sampler::Sampler* sampler, | 29 v8::Isolate* v8_isolate = isolate(); |
| 30 Isolate* i_isolate = reinterpret_cast<Isolate*>(v8_isolate); |
| 31 #if defined(USE_SIMULATOR) |
| 32 v8::RegisterState regs; |
| 33 if (!SimulatorHelper::FillRegisters(i_isolate, ®s)) return; |
| 34 #else |
| 35 const v8::RegisterState& regs = state; |
| 36 #endif |
| 37 TickSample* sample = processor_->StartTickSample(); |
| 38 if (sample == NULL) return; |
| 39 sample->Init(i_isolate, regs, TickSample::kIncludeCEntryFrame, true); |
| 40 if (is_counting_samples_ && !sample->timestamp.IsNull()) { |
| 41 if (sample->state == JS) ++js_sample_count_; |
| 42 if (sample->state == EXTERNAL) ++external_sample_count_; |
| 43 } |
| 44 processor_->FinishTickSample(); |
| 45 } |
| 46 |
| 47 private: |
| 48 ProfilerEventsProcessor* processor_; |
| 49 }; |
| 50 |
| 51 ProfilerEventsProcessor::ProfilerEventsProcessor(Isolate* isolate, |
| 52 ProfileGenerator* generator, |
| 25 base::TimeDelta period) | 53 base::TimeDelta period) |
| 26 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)), | 54 : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)), |
| 27 generator_(generator), | 55 generator_(generator), |
| 28 sampler_(sampler), | 56 sampler_(new CpuSampler(isolate, this)), |
| 29 running_(1), | 57 running_(1), |
| 30 period_(period), | 58 period_(period), |
| 31 last_code_event_id_(0), | 59 last_code_event_id_(0), |
| 32 last_processed_code_event_id_(0) {} | 60 last_processed_code_event_id_(0) { |
| 61 sampler_->IncreaseProfilingDepth(); |
| 62 } |
| 33 | 63 |
| 34 | 64 ProfilerEventsProcessor::~ProfilerEventsProcessor() { |
| 35 ProfilerEventsProcessor::~ProfilerEventsProcessor() {} | 65 sampler_->DecreaseProfilingDepth(); |
| 36 | 66 } |
| 37 | 67 |
| 38 void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) { | 68 void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) { |
| 39 event.generic.order = last_code_event_id_.Increment(1); | 69 event.generic.order = last_code_event_id_.Increment(1); |
| 40 events_buffer_.Enqueue(event); | 70 events_buffer_.Enqueue(event); |
| 41 } | 71 } |
| 42 | 72 |
| 43 | 73 |
| 44 void ProfilerEventsProcessor::AddDeoptStack(Isolate* isolate, Address from, | 74 void ProfilerEventsProcessor::AddDeoptStack(Isolate* isolate, Address from, |
| 45 int fp_to_sp_delta) { | 75 int fp_to_sp_delta) { |
| 46 TickSampleEventRecord record(last_code_event_id_.Value()); | 76 TickSampleEventRecord record(last_code_event_id_.Value()); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 | 306 |
| 277 void CpuProfiler::StartProcessorIfNotStarted() { | 307 void CpuProfiler::StartProcessorIfNotStarted() { |
| 278 if (processor_) { | 308 if (processor_) { |
| 279 processor_->AddCurrentStack(isolate_); | 309 processor_->AddCurrentStack(isolate_); |
| 280 return; | 310 return; |
| 281 } | 311 } |
| 282 Logger* logger = isolate_->logger(); | 312 Logger* logger = isolate_->logger(); |
| 283 // Disable logging when using the new implementation. | 313 // Disable logging when using the new implementation. |
| 284 saved_is_logging_ = logger->is_logging_; | 314 saved_is_logging_ = logger->is_logging_; |
| 285 logger->is_logging_ = false; | 315 logger->is_logging_ = false; |
| 286 sampler::Sampler* sampler = logger->sampler(); | |
| 287 generator_.reset(new ProfileGenerator(profiles_.get())); | 316 generator_.reset(new ProfileGenerator(profiles_.get())); |
| 288 processor_.reset(new ProfilerEventsProcessor(generator_.get(), sampler, | 317 processor_.reset(new ProfilerEventsProcessor(isolate_, generator_.get(), |
| 289 sampling_interval_)); | 318 sampling_interval_)); |
| 290 logger->SetUpProfilerListener(); | 319 logger->SetUpProfilerListener(); |
| 291 ProfilerListener* profiler_listener = logger->profiler_listener(); | 320 ProfilerListener* profiler_listener = logger->profiler_listener(); |
| 292 profiler_listener->AddObserver(this); | 321 profiler_listener->AddObserver(this); |
| 293 is_profiling_ = true; | 322 is_profiling_ = true; |
| 294 isolate_->set_is_profiling(true); | 323 isolate_->set_is_profiling(true); |
| 295 // Enumerate stuff we already have in the heap. | 324 // Enumerate stuff we already have in the heap. |
| 296 DCHECK(isolate_->heap()->HasBeenSetUp()); | 325 DCHECK(isolate_->heap()->HasBeenSetUp()); |
| 297 if (!FLAG_prof_browser_mode) { | 326 if (!FLAG_prof_browser_mode) { |
| 298 logger->LogCodeObjects(); | 327 logger->LogCodeObjects(); |
| 299 } | 328 } |
| 300 logger->LogCompiledFunctions(); | 329 logger->LogCompiledFunctions(); |
| 301 logger->LogAccessorCallbacks(); | 330 logger->LogAccessorCallbacks(); |
| 302 LogBuiltins(); | 331 LogBuiltins(); |
| 303 // Enable stack sampling. | 332 // Enable stack sampling. |
| 304 sampler->SetHasProcessingThread(true); | |
| 305 sampler->IncreaseProfilingDepth(); | |
| 306 processor_->AddCurrentStack(isolate_); | 333 processor_->AddCurrentStack(isolate_); |
| 307 processor_->StartSynchronously(); | 334 processor_->StartSynchronously(); |
| 308 } | 335 } |
| 309 | 336 |
| 310 | 337 |
| 311 CpuProfile* CpuProfiler::StopProfiling(const char* title) { | 338 CpuProfile* CpuProfiler::StopProfiling(const char* title) { |
| 312 if (!is_profiling_) return nullptr; | 339 if (!is_profiling_) return nullptr; |
| 313 StopProcessorIfLastProfile(title); | 340 StopProcessorIfLastProfile(title); |
| 314 CpuProfile* result = profiles_->StopProfiling(title); | 341 CpuProfile* result = profiles_->StopProfiling(title); |
| 315 if (result) { | 342 if (result) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 329 | 356 |
| 330 void CpuProfiler::StopProcessorIfLastProfile(const char* title) { | 357 void CpuProfiler::StopProcessorIfLastProfile(const char* title) { |
| 331 if (profiles_->IsLastProfile(title)) { | 358 if (profiles_->IsLastProfile(title)) { |
| 332 StopProcessor(); | 359 StopProcessor(); |
| 333 } | 360 } |
| 334 } | 361 } |
| 335 | 362 |
| 336 | 363 |
| 337 void CpuProfiler::StopProcessor() { | 364 void CpuProfiler::StopProcessor() { |
| 338 Logger* logger = isolate_->logger(); | 365 Logger* logger = isolate_->logger(); |
| 339 sampler::Sampler* sampler = | |
| 340 reinterpret_cast<sampler::Sampler*>(logger->ticker_); | |
| 341 is_profiling_ = false; | 366 is_profiling_ = false; |
| 342 isolate_->set_is_profiling(false); | 367 isolate_->set_is_profiling(false); |
| 343 ProfilerListener* profiler_listener = logger->profiler_listener(); | 368 ProfilerListener* profiler_listener = logger->profiler_listener(); |
| 344 profiler_listener->RemoveObserver(this); | 369 profiler_listener->RemoveObserver(this); |
| 345 processor_->StopSynchronously(); | 370 processor_->StopSynchronously(); |
| 346 logger->TearDownProfilerListener(); | 371 logger->TearDownProfilerListener(); |
| 347 processor_.reset(); | 372 processor_.reset(); |
| 348 generator_.reset(); | 373 generator_.reset(); |
| 349 sampler->SetHasProcessingThread(false); | |
| 350 sampler->DecreaseProfilingDepth(); | |
| 351 logger->is_logging_ = saved_is_logging_; | 374 logger->is_logging_ = saved_is_logging_; |
| 352 } | 375 } |
| 353 | 376 |
| 354 | 377 |
| 355 void CpuProfiler::LogBuiltins() { | 378 void CpuProfiler::LogBuiltins() { |
| 356 Builtins* builtins = isolate_->builtins(); | 379 Builtins* builtins = isolate_->builtins(); |
| 357 DCHECK(builtins->is_initialized()); | 380 DCHECK(builtins->is_initialized()); |
| 358 for (int i = 0; i < Builtins::builtin_count; i++) { | 381 for (int i = 0; i < Builtins::builtin_count; i++) { |
| 359 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN); | 382 CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN); |
| 360 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_; | 383 ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_; |
| 361 Builtins::Name id = static_cast<Builtins::Name>(i); | 384 Builtins::Name id = static_cast<Builtins::Name>(i); |
| 362 rec->start = builtins->builtin(id)->address(); | 385 rec->start = builtins->builtin(id)->address(); |
| 363 rec->builtin_id = id; | 386 rec->builtin_id = id; |
| 364 processor_->Enqueue(evt_rec); | 387 processor_->Enqueue(evt_rec); |
| 365 } | 388 } |
| 366 } | 389 } |
| 367 | 390 |
| 368 } // namespace internal | 391 } // namespace internal |
| 369 } // namespace v8 | 392 } // namespace v8 |
| OLD | NEW |