| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/sampler.h" | 5 #include "src/sampler.h" |
| 6 | 6 |
| 7 #if V8_OS_POSIX && !V8_OS_CYGWIN | 7 #if V8_OS_POSIX && !V8_OS_CYGWIN |
| 8 | 8 |
| 9 #define USE_SIGNALS | 9 #define USE_SIGNALS |
| 10 | 10 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #endif | 37 #endif |
| 38 | 38 |
| 39 #elif V8_OS_WIN || V8_OS_CYGWIN | 39 #elif V8_OS_WIN || V8_OS_CYGWIN |
| 40 | 40 |
| 41 #include "src/base/win32-headers.h" | 41 #include "src/base/win32-headers.h" |
| 42 | 42 |
| 43 #endif | 43 #endif |
| 44 | 44 |
| 45 #include "src/v8.h" | 45 #include "src/v8.h" |
| 46 | 46 |
| 47 #include "src/base/platform/platform.h" |
| 47 #include "src/cpu-profiler-inl.h" | 48 #include "src/cpu-profiler-inl.h" |
| 48 #include "src/flags.h" | 49 #include "src/flags.h" |
| 49 #include "src/frames-inl.h" | 50 #include "src/frames-inl.h" |
| 50 #include "src/log.h" | 51 #include "src/log.h" |
| 51 #include "src/platform.h" | |
| 52 #include "src/simulator.h" | 52 #include "src/simulator.h" |
| 53 #include "src/v8threads.h" | 53 #include "src/v8threads.h" |
| 54 #include "src/vm-state-inl.h" | 54 #include "src/vm-state-inl.h" |
| 55 | 55 |
| 56 | 56 |
| 57 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) | 57 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) |
| 58 | 58 |
| 59 // Not all versions of Android's C library provide ucontext_t. | 59 // Not all versions of Android's C library provide ucontext_t. |
| 60 // Detect this and provide custom but compatible definitions. Note that these | 60 // Detect this and provide custom but compatible definitions. Note that these |
| 61 // follow the GLibc naming convention to access register values from | 61 // follow the GLibc naming convention to access register values from |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 private: | 262 private: |
| 263 Simulator* simulator_; | 263 Simulator* simulator_; |
| 264 }; | 264 }; |
| 265 #endif // USE_SIMULATOR | 265 #endif // USE_SIMULATOR |
| 266 | 266 |
| 267 | 267 |
| 268 #if defined(USE_SIGNALS) | 268 #if defined(USE_SIGNALS) |
| 269 | 269 |
| 270 class SignalHandler : public AllStatic { | 270 class SignalHandler : public AllStatic { |
| 271 public: | 271 public: |
| 272 static void SetUp() { if (!mutex_) mutex_ = new Mutex(); } | 272 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } |
| 273 static void TearDown() { delete mutex_; } | 273 static void TearDown() { delete mutex_; } |
| 274 | 274 |
| 275 static void IncreaseSamplerCount() { | 275 static void IncreaseSamplerCount() { |
| 276 LockGuard<Mutex> lock_guard(mutex_); | 276 base::LockGuard<base::Mutex> lock_guard(mutex_); |
| 277 if (++client_count_ == 1) Install(); | 277 if (++client_count_ == 1) Install(); |
| 278 } | 278 } |
| 279 | 279 |
| 280 static void DecreaseSamplerCount() { | 280 static void DecreaseSamplerCount() { |
| 281 LockGuard<Mutex> lock_guard(mutex_); | 281 base::LockGuard<base::Mutex> lock_guard(mutex_); |
| 282 if (--client_count_ == 0) Restore(); | 282 if (--client_count_ == 0) Restore(); |
| 283 } | 283 } |
| 284 | 284 |
| 285 static bool Installed() { | 285 static bool Installed() { |
| 286 return signal_handler_installed_; | 286 return signal_handler_installed_; |
| 287 } | 287 } |
| 288 | 288 |
| 289 private: | 289 private: |
| 290 static void Install() { | 290 static void Install() { |
| 291 struct sigaction sa; | 291 struct sigaction sa; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 302 | 302 |
| 303 static void Restore() { | 303 static void Restore() { |
| 304 if (signal_handler_installed_) { | 304 if (signal_handler_installed_) { |
| 305 sigaction(SIGPROF, &old_signal_handler_, 0); | 305 sigaction(SIGPROF, &old_signal_handler_, 0); |
| 306 signal_handler_installed_ = false; | 306 signal_handler_installed_ = false; |
| 307 } | 307 } |
| 308 } | 308 } |
| 309 | 309 |
| 310 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); | 310 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
| 311 // Protects the process wide state below. | 311 // Protects the process wide state below. |
| 312 static Mutex* mutex_; | 312 static base::Mutex* mutex_; |
| 313 static int client_count_; | 313 static int client_count_; |
| 314 static bool signal_handler_installed_; | 314 static bool signal_handler_installed_; |
| 315 static struct sigaction old_signal_handler_; | 315 static struct sigaction old_signal_handler_; |
| 316 }; | 316 }; |
| 317 | 317 |
| 318 | 318 |
| 319 Mutex* SignalHandler::mutex_ = NULL; | 319 base::Mutex* SignalHandler::mutex_ = NULL; |
| 320 int SignalHandler::client_count_ = 0; | 320 int SignalHandler::client_count_ = 0; |
| 321 struct sigaction SignalHandler::old_signal_handler_; | 321 struct sigaction SignalHandler::old_signal_handler_; |
| 322 bool SignalHandler::signal_handler_installed_ = false; | 322 bool SignalHandler::signal_handler_installed_ = false; |
| 323 | 323 |
| 324 | 324 |
| 325 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, | 325 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
| 326 void* context) { | 326 void* context) { |
| 327 #if V8_OS_NACL | 327 #if V8_OS_NACL |
| 328 // As Native Client does not support signal handling, profiling | 328 // As Native Client does not support signal handling, profiling |
| 329 // is disabled. | 329 // is disabled. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 #endif // V8_HOST_ARCH_* | 466 #endif // V8_HOST_ARCH_* |
| 467 #endif // V8_OS_QNX | 467 #endif // V8_OS_QNX |
| 468 #endif // USE_SIMULATOR | 468 #endif // USE_SIMULATOR |
| 469 sampler->SampleStack(state); | 469 sampler->SampleStack(state); |
| 470 #endif // V8_OS_NACL | 470 #endif // V8_OS_NACL |
| 471 } | 471 } |
| 472 | 472 |
| 473 #endif | 473 #endif |
| 474 | 474 |
| 475 | 475 |
| 476 class SamplerThread : public Thread { | 476 class SamplerThread : public base::Thread { |
| 477 public: | 477 public: |
| 478 static const int kSamplerThreadStackSize = 64 * KB; | 478 static const int kSamplerThreadStackSize = 64 * KB; |
| 479 | 479 |
| 480 explicit SamplerThread(int interval) | 480 explicit SamplerThread(int interval) |
| 481 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), | 481 : Thread(base::Thread::Options("SamplerThread", kSamplerThreadStackSize)), |
| 482 interval_(interval) {} | 482 interval_(interval) {} |
| 483 | 483 |
| 484 static void SetUp() { if (!mutex_) mutex_ = new Mutex(); } | 484 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } |
| 485 static void TearDown() { delete mutex_; mutex_ = NULL; } | 485 static void TearDown() { delete mutex_; mutex_ = NULL; } |
| 486 | 486 |
| 487 static void AddActiveSampler(Sampler* sampler) { | 487 static void AddActiveSampler(Sampler* sampler) { |
| 488 bool need_to_start = false; | 488 bool need_to_start = false; |
| 489 LockGuard<Mutex> lock_guard(mutex_); | 489 base::LockGuard<base::Mutex> lock_guard(mutex_); |
| 490 if (instance_ == NULL) { | 490 if (instance_ == NULL) { |
| 491 // Start a thread that will send SIGPROF signal to VM threads, | 491 // Start a thread that will send SIGPROF signal to VM threads, |
| 492 // when CPU profiling will be enabled. | 492 // when CPU profiling will be enabled. |
| 493 instance_ = new SamplerThread(sampler->interval()); | 493 instance_ = new SamplerThread(sampler->interval()); |
| 494 need_to_start = true; | 494 need_to_start = true; |
| 495 } | 495 } |
| 496 | 496 |
| 497 ASSERT(sampler->IsActive()); | 497 ASSERT(sampler->IsActive()); |
| 498 ASSERT(!instance_->active_samplers_.Contains(sampler)); | 498 ASSERT(!instance_->active_samplers_.Contains(sampler)); |
| 499 ASSERT(instance_->interval_ == sampler->interval()); | 499 ASSERT(instance_->interval_ == sampler->interval()); |
| 500 instance_->active_samplers_.Add(sampler); | 500 instance_->active_samplers_.Add(sampler); |
| 501 | 501 |
| 502 if (need_to_start) instance_->StartSynchronously(); | 502 if (need_to_start) instance_->StartSynchronously(); |
| 503 } | 503 } |
| 504 | 504 |
| 505 static void RemoveActiveSampler(Sampler* sampler) { | 505 static void RemoveActiveSampler(Sampler* sampler) { |
| 506 SamplerThread* instance_to_remove = NULL; | 506 SamplerThread* instance_to_remove = NULL; |
| 507 { | 507 { |
| 508 LockGuard<Mutex> lock_guard(mutex_); | 508 base::LockGuard<base::Mutex> lock_guard(mutex_); |
| 509 | 509 |
| 510 ASSERT(sampler->IsActive()); | 510 ASSERT(sampler->IsActive()); |
| 511 bool removed = instance_->active_samplers_.RemoveElement(sampler); | 511 bool removed = instance_->active_samplers_.RemoveElement(sampler); |
| 512 ASSERT(removed); | 512 ASSERT(removed); |
| 513 USE(removed); | 513 USE(removed); |
| 514 | 514 |
| 515 // We cannot delete the instance immediately as we need to Join() the | 515 // We cannot delete the instance immediately as we need to Join() the |
| 516 // thread but we are holding mutex_ and the thread may try to acquire it. | 516 // thread but we are holding mutex_ and the thread may try to acquire it. |
| 517 if (instance_->active_samplers_.is_empty()) { | 517 if (instance_->active_samplers_.is_empty()) { |
| 518 instance_to_remove = instance_; | 518 instance_to_remove = instance_; |
| 519 instance_ = NULL; | 519 instance_ = NULL; |
| 520 } | 520 } |
| 521 } | 521 } |
| 522 | 522 |
| 523 if (!instance_to_remove) return; | 523 if (!instance_to_remove) return; |
| 524 instance_to_remove->Join(); | 524 instance_to_remove->Join(); |
| 525 delete instance_to_remove; | 525 delete instance_to_remove; |
| 526 } | 526 } |
| 527 | 527 |
| 528 // Implement Thread::Run(). | 528 // Implement Thread::Run(). |
| 529 virtual void Run() { | 529 virtual void Run() { |
| 530 while (true) { | 530 while (true) { |
| 531 { | 531 { |
| 532 LockGuard<Mutex> lock_guard(mutex_); | 532 base::LockGuard<base::Mutex> lock_guard(mutex_); |
| 533 if (active_samplers_.is_empty()) break; | 533 if (active_samplers_.is_empty()) break; |
| 534 // When CPU profiling is enabled both JavaScript and C++ code is | 534 // When CPU profiling is enabled both JavaScript and C++ code is |
| 535 // profiled. We must not suspend. | 535 // profiled. We must not suspend. |
| 536 for (int i = 0; i < active_samplers_.length(); ++i) { | 536 for (int i = 0; i < active_samplers_.length(); ++i) { |
| 537 Sampler* sampler = active_samplers_.at(i); | 537 Sampler* sampler = active_samplers_.at(i); |
| 538 if (!sampler->isolate()->IsInitialized()) continue; | 538 if (!sampler->isolate()->IsInitialized()) continue; |
| 539 if (!sampler->IsProfiling()) continue; | 539 if (!sampler->IsProfiling()) continue; |
| 540 sampler->DoSample(); | 540 sampler->DoSample(); |
| 541 } | 541 } |
| 542 } | 542 } |
| 543 OS::Sleep(interval_); | 543 base::OS::Sleep(interval_); |
| 544 } | 544 } |
| 545 } | 545 } |
| 546 | 546 |
| 547 private: | 547 private: |
| 548 // Protects the process wide state below. | 548 // Protects the process wide state below. |
| 549 static Mutex* mutex_; | 549 static base::Mutex* mutex_; |
| 550 static SamplerThread* instance_; | 550 static SamplerThread* instance_; |
| 551 | 551 |
| 552 const int interval_; | 552 const int interval_; |
| 553 List<Sampler*> active_samplers_; | 553 List<Sampler*> active_samplers_; |
| 554 | 554 |
| 555 DISALLOW_COPY_AND_ASSIGN(SamplerThread); | 555 DISALLOW_COPY_AND_ASSIGN(SamplerThread); |
| 556 }; | 556 }; |
| 557 | 557 |
| 558 | 558 |
| 559 Mutex* SamplerThread::mutex_ = NULL; | 559 base::Mutex* SamplerThread::mutex_ = NULL; |
| 560 SamplerThread* SamplerThread::instance_ = NULL; | 560 SamplerThread* SamplerThread::instance_ = NULL; |
| 561 | 561 |
| 562 | 562 |
| 563 // | 563 // |
| 564 // StackTracer implementation | 564 // StackTracer implementation |
| 565 // | 565 // |
| 566 DISABLE_ASAN void TickSample::Init(Isolate* isolate, | 566 DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
| 567 const RegisterState& regs) { | 567 const RegisterState& regs) { |
| 568 ASSERT(isolate->IsInitialized()); | 568 ASSERT(isolate->IsInitialized()); |
| 569 timestamp = TimeTicks::HighResolutionNow(); | 569 timestamp = base::TimeTicks::HighResolutionNow(); |
| 570 pc = regs.pc; | 570 pc = regs.pc; |
| 571 state = isolate->current_vm_state(); | 571 state = isolate->current_vm_state(); |
| 572 | 572 |
| 573 // Avoid collecting traces while doing GC. | 573 // Avoid collecting traces while doing GC. |
| 574 if (state == GC) return; | 574 if (state == GC) return; |
| 575 | 575 |
| 576 Address js_entry_sp = isolate->js_entry_sp(); | 576 Address js_entry_sp = isolate->js_entry_sp(); |
| 577 if (js_entry_sp == 0) { | 577 if (js_entry_sp == 0) { |
| 578 // Not executing JS now. | 578 // Not executing JS now. |
| 579 return; | 579 return; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 #endif // USE_SIMULATOR | 728 #endif // USE_SIMULATOR |
| 729 SampleStack(state); | 729 SampleStack(state); |
| 730 } | 730 } |
| 731 ResumeThread(profiled_thread); | 731 ResumeThread(profiled_thread); |
| 732 } | 732 } |
| 733 | 733 |
| 734 #endif // USE_SIGNALS | 734 #endif // USE_SIGNALS |
| 735 | 735 |
| 736 | 736 |
| 737 } } // namespace v8::internal | 737 } } // namespace v8::internal |
| OLD | NEW |