| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 private: | 241 private: |
| 242 Simulator* simulator_; | 242 Simulator* simulator_; |
| 243 }; | 243 }; |
| 244 #endif // USE_SIMULATOR | 244 #endif // USE_SIMULATOR |
| 245 | 245 |
| 246 | 246 |
| 247 #if defined(USE_SIGNALS) | 247 #if defined(USE_SIGNALS) |
| 248 | 248 |
| 249 class SignalHandler : public AllStatic { | 249 class SignalHandler : public AllStatic { |
| 250 public: | 250 public: |
| 251 static inline void EnsureInstalled() { | 251 static void SetUp() { if (!mutex_) mutex_ = new Mutex(); } |
| 252 if (signal_handler_installed_) return; | 252 static void TearDown() { delete mutex_; } |
| 253 |
| 254 static void IncreaseSamplerCount() { |
| 255 LockGuard<Mutex> lock_guard(mutex_); |
| 256 if (++client_count_ == 1) Install(); |
| 257 } |
| 258 |
| 259 static void DecreaseSamplerCount() { |
| 260 LockGuard<Mutex> lock_guard(mutex_); |
| 261 if (--client_count_ == 0) Restore(); |
| 262 } |
| 263 |
| 264 static bool Installed() { |
| 265 return signal_handler_installed_; |
| 266 } |
| 267 |
| 268 private: |
| 269 static void Install() { |
| 253 struct sigaction sa; | 270 struct sigaction sa; |
| 254 sa.sa_sigaction = &HandleProfilerSignal; | 271 sa.sa_sigaction = &HandleProfilerSignal; |
| 255 sigemptyset(&sa.sa_mask); | 272 sigemptyset(&sa.sa_mask); |
| 256 sa.sa_flags = SA_RESTART | SA_SIGINFO; | 273 sa.sa_flags = SA_RESTART | SA_SIGINFO; |
| 257 signal_handler_installed_ = | 274 signal_handler_installed_ = |
| 258 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); | 275 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
| 259 } | 276 } |
| 260 | 277 |
| 261 static inline void Restore() { | 278 static void Restore() { |
| 262 if (signal_handler_installed_) { | 279 if (signal_handler_installed_) { |
| 263 sigaction(SIGPROF, &old_signal_handler_, 0); | 280 sigaction(SIGPROF, &old_signal_handler_, 0); |
| 264 signal_handler_installed_ = false; | 281 signal_handler_installed_ = false; |
| 265 } | 282 } |
| 266 } | 283 } |
| 267 | 284 |
| 268 static inline bool Installed() { | |
| 269 return signal_handler_installed_; | |
| 270 } | |
| 271 | |
| 272 private: | |
| 273 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); | 285 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
| 286 // Protects the process wide state below. |
| 287 static Mutex* mutex_; |
| 288 static int client_count_; |
| 274 static bool signal_handler_installed_; | 289 static bool signal_handler_installed_; |
| 275 static struct sigaction old_signal_handler_; | 290 static struct sigaction old_signal_handler_; |
| 276 }; | 291 }; |
| 277 | 292 |
| 293 |
| 294 Mutex* SignalHandler::mutex_ = NULL; |
| 295 int SignalHandler::client_count_ = 0; |
| 278 struct sigaction SignalHandler::old_signal_handler_; | 296 struct sigaction SignalHandler::old_signal_handler_; |
| 279 bool SignalHandler::signal_handler_installed_ = false; | 297 bool SignalHandler::signal_handler_installed_ = false; |
| 280 | 298 |
| 281 | 299 |
| 282 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, | 300 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
| 283 void* context) { | 301 void* context) { |
| 284 #if V8_OS_NACL | 302 #if V8_OS_NACL |
| 285 // As Native Client does not support signal handling, profiling | 303 // As Native Client does not support signal handling, profiling |
| 286 // is disabled. | 304 // is disabled. |
| 287 return; | 305 return; |
| 288 #else | 306 #else |
| 289 USE(info); | 307 USE(info); |
| 290 if (signal != SIGPROF) return; | 308 if (signal != SIGPROF) return; |
| 291 Isolate* isolate = Isolate::UncheckedCurrent(); | 309 Isolate* isolate = Isolate::UncheckedCurrent(); |
| 292 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { | 310 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { |
| 293 // We require a fully initialized and entered isolate. | 311 // We require a fully initialized and entered isolate. |
| 294 return; | 312 return; |
| 295 } | 313 } |
| 296 if (v8::Locker::IsActive() && | 314 if (v8::Locker::IsActive() && |
| 297 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 315 !isolate->thread_manager()->IsLockedByCurrentThread()) { |
| 298 return; | 316 return; |
| 299 } | 317 } |
| 300 | 318 |
| 301 Sampler* sampler = isolate->logger()->sampler(); | 319 Sampler* sampler = isolate->logger()->sampler(); |
| 302 if (sampler == NULL || !sampler->IsActive()) return; | 320 if (sampler == NULL) return; |
| 303 | 321 |
| 304 RegisterState state; | 322 RegisterState state; |
| 305 | 323 |
| 306 #if defined(USE_SIMULATOR) | 324 #if defined(USE_SIMULATOR) |
| 307 SimulatorHelper helper; | 325 SimulatorHelper helper; |
| 308 if (!helper.Init(sampler, isolate)) return; | 326 if (!helper.Init(sampler, isolate)) return; |
| 309 helper.FillRegisters(&state); | 327 helper.FillRegisters(&state); |
| 310 #else | 328 #else |
| 311 // Extracting the sample from the context is extremely machine dependent. | 329 // Extracting the sample from the context is extremely machine dependent. |
| 312 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 330 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 // when CPU profiling will be enabled. | 447 // when CPU profiling will be enabled. |
| 430 instance_ = new SamplerThread(sampler->interval()); | 448 instance_ = new SamplerThread(sampler->interval()); |
| 431 need_to_start = true; | 449 need_to_start = true; |
| 432 } | 450 } |
| 433 | 451 |
| 434 ASSERT(sampler->IsActive()); | 452 ASSERT(sampler->IsActive()); |
| 435 ASSERT(!instance_->active_samplers_.Contains(sampler)); | 453 ASSERT(!instance_->active_samplers_.Contains(sampler)); |
| 436 ASSERT(instance_->interval_ == sampler->interval()); | 454 ASSERT(instance_->interval_ == sampler->interval()); |
| 437 instance_->active_samplers_.Add(sampler); | 455 instance_->active_samplers_.Add(sampler); |
| 438 | 456 |
| 439 #if defined(USE_SIGNALS) | |
| 440 SignalHandler::EnsureInstalled(); | |
| 441 #endif | |
| 442 if (need_to_start) instance_->StartSynchronously(); | 457 if (need_to_start) instance_->StartSynchronously(); |
| 443 } | 458 } |
| 444 | 459 |
| 445 static void RemoveActiveSampler(Sampler* sampler) { | 460 static void RemoveActiveSampler(Sampler* sampler) { |
| 446 SamplerThread* instance_to_remove = NULL; | 461 SamplerThread* instance_to_remove = NULL; |
| 447 { | 462 { |
| 448 LockGuard<Mutex> lock_guard(mutex_); | 463 LockGuard<Mutex> lock_guard(mutex_); |
| 449 | 464 |
| 450 ASSERT(sampler->IsActive()); | 465 ASSERT(sampler->IsActive()); |
| 451 bool removed = instance_->active_samplers_.RemoveElement(sampler); | 466 bool removed = instance_->active_samplers_.RemoveElement(sampler); |
| 452 ASSERT(removed); | 467 ASSERT(removed); |
| 453 USE(removed); | 468 USE(removed); |
| 454 | 469 |
| 455 // We cannot delete the instance immediately as we need to Join() the | 470 // We cannot delete the instance immediately as we need to Join() the |
| 456 // thread but we are holding mutex_ and the thread may try to acquire it. | 471 // thread but we are holding mutex_ and the thread may try to acquire it. |
| 457 if (instance_->active_samplers_.is_empty()) { | 472 if (instance_->active_samplers_.is_empty()) { |
| 458 instance_to_remove = instance_; | 473 instance_to_remove = instance_; |
| 459 instance_ = NULL; | 474 instance_ = NULL; |
| 460 #if defined(USE_SIGNALS) | |
| 461 SignalHandler::Restore(); | |
| 462 #endif | |
| 463 } | 475 } |
| 464 } | 476 } |
| 465 | 477 |
| 466 if (!instance_to_remove) return; | 478 if (!instance_to_remove) return; |
| 467 instance_to_remove->Join(); | 479 instance_to_remove->Join(); |
| 468 delete instance_to_remove; | 480 delete instance_to_remove; |
| 469 } | 481 } |
| 470 | 482 |
| 471 // Implement Thread::Run(). | 483 // Implement Thread::Run(). |
| 472 virtual void Run() { | 484 virtual void Run() { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 int i = 0; | 553 int i = 0; |
| 542 while (!it.done() && i < TickSample::kMaxFramesCount) { | 554 while (!it.done() && i < TickSample::kMaxFramesCount) { |
| 543 stack[i++] = it.frame()->pc(); | 555 stack[i++] = it.frame()->pc(); |
| 544 it.Advance(); | 556 it.Advance(); |
| 545 } | 557 } |
| 546 frames_count = i; | 558 frames_count = i; |
| 547 } | 559 } |
| 548 | 560 |
| 549 | 561 |
| 550 void Sampler::SetUp() { | 562 void Sampler::SetUp() { |
| 563 #if defined(USE_SIGNALS) |
| 564 SignalHandler::SetUp(); |
| 565 #endif |
| 551 SamplerThread::SetUp(); | 566 SamplerThread::SetUp(); |
| 552 } | 567 } |
| 553 | 568 |
| 554 | 569 |
| 555 void Sampler::TearDown() { | 570 void Sampler::TearDown() { |
| 556 SamplerThread::TearDown(); | 571 SamplerThread::TearDown(); |
| 572 #if defined(USE_SIGNALS) |
| 573 SignalHandler::TearDown(); |
| 574 #endif |
| 557 } | 575 } |
| 558 | 576 |
| 559 | 577 |
| 560 Sampler::Sampler(Isolate* isolate, int interval) | 578 Sampler::Sampler(Isolate* isolate, int interval) |
| 561 : isolate_(isolate), | 579 : isolate_(isolate), |
| 562 interval_(interval), | 580 interval_(interval), |
| 563 profiling_(false), | 581 profiling_(false), |
| 564 has_processing_thread_(false), | 582 has_processing_thread_(false), |
| 565 active_(false), | 583 active_(false), |
| 566 is_counting_samples_(false), | 584 is_counting_samples_(false), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 582 } | 600 } |
| 583 | 601 |
| 584 | 602 |
| 585 void Sampler::Stop() { | 603 void Sampler::Stop() { |
| 586 ASSERT(IsActive()); | 604 ASSERT(IsActive()); |
| 587 SamplerThread::RemoveActiveSampler(this); | 605 SamplerThread::RemoveActiveSampler(this); |
| 588 SetActive(false); | 606 SetActive(false); |
| 589 } | 607 } |
| 590 | 608 |
| 591 | 609 |
| 610 void Sampler::IncreaseProfilingDepth() { |
| 611 NoBarrier_AtomicIncrement(&profiling_, 1); |
| 612 #if defined(USE_SIGNALS) |
| 613 SignalHandler::IncreaseSamplerCount(); |
| 614 #endif |
| 615 } |
| 616 |
| 617 |
| 618 void Sampler::DecreaseProfilingDepth() { |
| 619 #if defined(USE_SIGNALS) |
| 620 SignalHandler::DecreaseSamplerCount(); |
| 621 #endif |
| 622 NoBarrier_AtomicIncrement(&profiling_, -1); |
| 623 } |
| 624 |
| 625 |
| 592 void Sampler::SampleStack(const RegisterState& state) { | 626 void Sampler::SampleStack(const RegisterState& state) { |
| 593 TickSample* sample = isolate_->cpu_profiler()->StartTickSample(); | 627 TickSample* sample = isolate_->cpu_profiler()->StartTickSample(); |
| 594 TickSample sample_obj; | 628 TickSample sample_obj; |
| 595 if (sample == NULL) sample = &sample_obj; | 629 if (sample == NULL) sample = &sample_obj; |
| 596 sample->Init(isolate_, state); | 630 sample->Init(isolate_, state); |
| 597 if (is_counting_samples_) { | 631 if (is_counting_samples_) { |
| 598 if (sample->state == JS || sample->state == EXTERNAL) { | 632 if (sample->state == JS || sample->state == EXTERNAL) { |
| 599 ++js_and_external_sample_count_; | 633 ++js_and_external_sample_count_; |
| 600 } | 634 } |
| 601 } | 635 } |
| 602 Tick(sample); | 636 Tick(sample); |
| 603 if (sample != &sample_obj) { | 637 if (sample != &sample_obj) { |
| 604 isolate_->cpu_profiler()->FinishTickSample(); | 638 isolate_->cpu_profiler()->FinishTickSample(); |
| 605 } | 639 } |
| 606 } | 640 } |
| 607 | 641 |
| 608 | 642 |
| 609 bool Sampler::CanSampleOnProfilerEventsProcessorThread() { | |
| 610 #if defined(USE_SIGNALS) | |
| 611 return true; | |
| 612 #elif V8_OS_WIN || V8_OS_CYGWIN | |
| 613 return true; | |
| 614 #else | |
| 615 return false; | |
| 616 #endif | |
| 617 } | |
| 618 | |
| 619 | |
| 620 #if defined(USE_SIGNALS) | 643 #if defined(USE_SIGNALS) |
| 621 | 644 |
| 622 void Sampler::DoSample() { | 645 void Sampler::DoSample() { |
| 623 if (!SignalHandler::Installed()) return; | 646 if (!SignalHandler::Installed()) return; |
| 624 pthread_kill(platform_data()->vm_tid(), SIGPROF); | 647 pthread_kill(platform_data()->vm_tid(), SIGPROF); |
| 625 } | 648 } |
| 626 | 649 |
| 627 #elif V8_OS_WIN || V8_OS_CYGWIN | 650 #elif V8_OS_WIN || V8_OS_CYGWIN |
| 628 | 651 |
| 629 void Sampler::DoSample() { | 652 void Sampler::DoSample() { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 659 #endif // USE_SIMULATOR | 682 #endif // USE_SIMULATOR |
| 660 SampleStack(state); | 683 SampleStack(state); |
| 661 } | 684 } |
| 662 ResumeThread(profiled_thread); | 685 ResumeThread(profiled_thread); |
| 663 } | 686 } |
| 664 | 687 |
| 665 #endif // USE_SIGNALS | 688 #endif // USE_SIGNALS |
| 666 | 689 |
| 667 | 690 |
| 668 } } // namespace v8::internal | 691 } } // namespace v8::internal |
| OLD | NEW |