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 |