Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: src/sampler.cc

Issue 14293009: Nuke SamplerRegistry (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/log.cc ('k') | src/v8.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 #endif 58 #endif
59 59
60 #include "v8.h" 60 #include "v8.h"
61 61
62 #include "log.h" 62 #include "log.h"
63 #include "platform.h" 63 #include "platform.h"
64 #include "simulator.h" 64 #include "simulator.h"
65 #include "v8threads.h" 65 #include "v8threads.h"
66 66
67 67
68 namespace v8 {
69 namespace internal {
70
71
72 #if defined(USE_SIGNALS)
73
74 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) 68 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
75 69
76 // Not all versions of Android's C library provide ucontext_t. 70 // Not all versions of Android's C library provide ucontext_t.
77 // Detect this and provide custom but compatible definitions. Note that these 71 // Detect this and provide custom but compatible definitions. Note that these
78 // follow the GLibc naming convention to access register values from 72 // follow the GLibc naming convention to access register values from
79 // mcontext_t. 73 // mcontext_t.
80 // 74 //
81 // See http://code.google.com/p/android/issues/detail?id=34784 75 // See http://code.google.com/p/android/issues/detail?id=34784
82 76
83 #if defined(__arm__) 77 #if defined(__arm__)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 stack_t uc_stack; 133 stack_t uc_stack;
140 mcontext_t uc_mcontext; 134 mcontext_t uc_mcontext;
141 // Other fields are not used by V8, don't define them here. 135 // Other fields are not used by V8, don't define them here.
142 } ucontext_t; 136 } ucontext_t;
143 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; 137 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
144 #endif 138 #endif
145 139
146 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T) 140 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)
147 141
148 142
143 namespace v8 {
144 namespace internal {
145
146 #if defined(USE_SIGNALS)
147
149 class Sampler::PlatformData : public Malloced { 148 class Sampler::PlatformData : public Malloced {
150 public: 149 public:
151 PlatformData() 150 PlatformData()
152 : vm_tid_(pthread_self()), 151 : vm_tid_(pthread_self()),
153 profiled_thread_id_(ThreadId::Current()) {} 152 profiled_thread_id_(ThreadId::Current()) {}
154 153
155 pthread_t vm_tid() const { return vm_tid_; } 154 pthread_t vm_tid() const { return vm_tid_; }
156 ThreadId profiled_thread_id() { return profiled_thread_id_; } 155 ThreadId profiled_thread_id() { return profiled_thread_id_; }
157 156
158 private: 157 private:
159 pthread_t vm_tid_; 158 pthread_t vm_tid_;
160 ThreadId profiled_thread_id_; 159 ThreadId profiled_thread_id_;
161 }; 160 };
162 161
163 162
164 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 163 class SignalHandler : public AllStatic {
164 public:
165 static inline void EnsureInstalled() {
166 if (signal_handler_installed_) return;
167 struct sigaction sa;
168 sa.sa_sigaction = &HandleProfilerSignal;
169 sigemptyset(&sa.sa_mask);
170 sa.sa_flags = SA_RESTART | SA_SIGINFO;
171 signal_handler_installed_ =
172 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
173 }
174
175 static inline void Restore() {
176 if (signal_handler_installed_) {
177 sigaction(SIGPROF, &old_signal_handler_, 0);
178 signal_handler_installed_ = false;
179 }
180 }
181
182 static inline bool Installed() {
183 return signal_handler_installed_;
184 }
185
186 private:
187 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
188 static bool signal_handler_installed_;
189 static struct sigaction old_signal_handler_;
190 };
191
192 struct sigaction SignalHandler::old_signal_handler_;
193 bool SignalHandler::signal_handler_installed_ = false;
194
195
196 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
197 void* context) {
165 #if defined(__native_client__) 198 #if defined(__native_client__)
166 // As Native Client does not support signal handling, profiling 199 // As Native Client does not support signal handling, profiling
167 // is disabled. 200 // is disabled.
168 return; 201 return;
169 #else 202 #else
170 USE(info); 203 USE(info);
171 if (signal != SIGPROF) return; 204 if (signal != SIGPROF) return;
172 Isolate* isolate = Isolate::UncheckedCurrent(); 205 Isolate* isolate = Isolate::UncheckedCurrent();
173 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 206 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
174 // We require a fully initialized and entered isolate. 207 // We require a fully initialized and entered isolate.
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 public: 387 public:
355 static const int kSamplerThreadStackSize = 64 * KB; 388 static const int kSamplerThreadStackSize = 64 * KB;
356 389
357 explicit SamplerThread(int interval) 390 explicit SamplerThread(int interval)
358 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), 391 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
359 interval_(interval) {} 392 interval_(interval) {}
360 393
361 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } 394 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
362 static void TearDown() { delete mutex_; } 395 static void TearDown() { delete mutex_; }
363 396
364 #if defined(USE_SIGNALS)
365 static void InstallSignalHandler() {
366 struct sigaction sa;
367 sa.sa_sigaction = ProfilerSignalHandler;
368 sigemptyset(&sa.sa_mask);
369 sa.sa_flags = SA_RESTART | SA_SIGINFO;
370 signal_handler_installed_ =
371 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
372 }
373
374 static void RestoreSignalHandler() {
375 if (signal_handler_installed_) {
376 sigaction(SIGPROF, &old_signal_handler_, 0);
377 signal_handler_installed_ = false;
378 }
379 }
380 #endif
381
382 static void AddActiveSampler(Sampler* sampler) { 397 static void AddActiveSampler(Sampler* sampler) {
398 bool need_to_start = false;
383 ScopedLock lock(mutex_); 399 ScopedLock lock(mutex_);
384 SamplerRegistry::AddActiveSampler(sampler);
385 if (instance_ == NULL) { 400 if (instance_ == NULL) {
386 // Start a thread that will send SIGPROF signal to VM threads, 401 // Start a thread that will send SIGPROF signal to VM threads,
387 // when CPU profiling will be enabled. 402 // when CPU profiling will be enabled.
388 instance_ = new SamplerThread(sampler->interval()); 403 instance_ = new SamplerThread(sampler->interval());
389 instance_->StartSynchronously(); 404 need_to_start = true;
390 } else {
391 ASSERT(instance_->interval_ == sampler->interval());
392 } 405 }
406
407 ASSERT(sampler->IsActive());
408 ASSERT(!instance_->active_samplers_.Contains(sampler));
409 ASSERT(instance_->interval_ == sampler->interval());
410 instance_->active_samplers_.Add(sampler);
411
412 #if defined(USE_SIGNALS)
413 SignalHandler::EnsureInstalled();
414 #endif
415 if (need_to_start) instance_->StartSynchronously();
393 } 416 }
394 417
395 static void RemoveActiveSampler(Sampler* sampler) { 418 static void RemoveActiveSampler(Sampler* sampler) {
396 ScopedLock lock(mutex_); 419 SamplerThread* instance_to_remove = NULL;
397 SamplerRegistry::RemoveActiveSampler(sampler); 420 {
398 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 421 ScopedLock lock(mutex_);
399 instance_->Join(); 422
400 delete instance_; 423 ASSERT(sampler->IsActive());
401 instance_ = NULL; 424 bool removed = instance_->active_samplers_.RemoveElement(sampler);
425 ASSERT(removed);
426 USE(removed);
427
428 // We cannot delete the instance immediately as we need to Join() the
429 // thread but we are holding mutex_ and the thread may try to acquire it.
430 if (instance_->active_samplers_.is_empty()) {
431 instance_to_remove = instance_;
432 instance_ = NULL;
402 #if defined(USE_SIGNALS) 433 #if defined(USE_SIGNALS)
403 RestoreSignalHandler(); 434 SignalHandler::Restore();
404 #endif 435 #endif
436 }
405 } 437 }
438
439 if (!instance_to_remove) return;
440 instance_to_remove->Join();
441 delete instance_to_remove;
406 } 442 }
407 443
408 // Implement Thread::Run(). 444 // Implement Thread::Run().
409 virtual void Run() { 445 virtual void Run() {
410 SamplerRegistry::State state; 446 while (true) {
411 while ((state = SamplerRegistry::GetState()) != 447 {
412 SamplerRegistry::HAS_NO_SAMPLERS) { 448 ScopedLock lock(mutex_);
413 // When CPU profiling is enabled both JavaScript and C++ code is 449 if (active_samplers_.is_empty()) break;
414 // profiled. We must not suspend. 450 // When CPU profiling is enabled both JavaScript and C++ code is
415 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { 451 // profiled. We must not suspend.
416 #if defined(USE_SIGNALS) 452 for (int i = 0; i < active_samplers_.length(); ++i) {
417 if (!signal_handler_installed_) InstallSignalHandler(); 453 Sampler* sampler = active_samplers_.at(i);
418 #endif 454 if (!sampler->isolate()->IsInitialized()) continue;
419 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); 455 if (!sampler->IsProfiling()) continue;
420 } else { 456 SampleContext(sampler);
421 #if defined(USE_SIGNALS) 457 }
422 if (signal_handler_installed_) RestoreSignalHandler();
423 #endif
424 } 458 }
425 OS::Sleep(interval_); 459 OS::Sleep(interval_);
426 } 460 }
427 } 461 }
428 462
429 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 463 private:
430 if (!sampler->isolate()->IsInitialized()) return;
431 if (!sampler->IsProfiling()) return;
432 SamplerThread* sender = reinterpret_cast<SamplerThread*>(raw_sender);
433 sender->SampleContext(sampler);
434 }
435
436 #if defined(USE_SIGNALS) 464 #if defined(USE_SIGNALS)
437 465
438 void SampleContext(Sampler* sampler) { 466 void SampleContext(Sampler* sampler) {
439 if (!signal_handler_installed_) return; 467 if (!SignalHandler::Installed()) return;
440 pthread_t tid = sampler->platform_data()->vm_tid(); 468 pthread_t tid = sampler->platform_data()->vm_tid();
441 int result = pthread_kill(tid, SIGPROF); 469 int result = pthread_kill(tid, SIGPROF);
442 USE(result); 470 USE(result);
443 ASSERT(result == 0); 471 ASSERT(result == 0);
444 } 472 }
445 473
446 #elif defined(__MACH__) 474 #elif defined(__MACH__)
447 475
448 void SampleContext(Sampler* sampler) { 476 void SampleContext(Sampler* sampler) {
449 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); 477 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 #endif 596 #endif
569 #endif // USE_SIMULATOR 597 #endif // USE_SIMULATOR
570 sampler->SampleStack(sample); 598 sampler->SampleStack(sample);
571 sampler->Tick(sample); 599 sampler->Tick(sample);
572 } 600 }
573 ResumeThread(profiled_thread); 601 ResumeThread(profiled_thread);
574 } 602 }
575 603
576 #endif // USE_SIGNALS 604 #endif // USE_SIGNALS
577 605
578 const int interval_;
579 606
580 // Protects the process wide state below. 607 // Protects the process wide state below.
581 static Mutex* mutex_; 608 static Mutex* mutex_;
582 static SamplerThread* instance_; 609 static SamplerThread* instance_;
583 #if defined(USE_SIGNALS)
584 static bool signal_handler_installed_;
585 static struct sigaction old_signal_handler_;
586 #endif
587 610
588 private: 611 const int interval_;
612 List<Sampler*> active_samplers_;
613
589 DISALLOW_COPY_AND_ASSIGN(SamplerThread); 614 DISALLOW_COPY_AND_ASSIGN(SamplerThread);
590 }; 615 };
591 616
592 617
593 Mutex* SamplerThread::mutex_ = NULL; 618 Mutex* SamplerThread::mutex_ = NULL;
594 SamplerThread* SamplerThread::instance_ = NULL; 619 SamplerThread* SamplerThread::instance_ = NULL;
595 #if defined(USE_SIGNALS)
596 struct sigaction SamplerThread::old_signal_handler_;
597 bool SamplerThread::signal_handler_installed_ = false;
598 #endif
599 620
600 621
601 void Sampler::SetUp() { 622 void Sampler::SetUp() {
602 SamplerThread::SetUp(); 623 SamplerThread::SetUp();
603 } 624 }
604 625
605 626
606 void Sampler::TearDown() { 627 void Sampler::TearDown() {
607 SamplerThread::TearDown(); 628 SamplerThread::TearDown();
608 } 629 }
(...skipping 26 matching lines...) Expand all
635 SamplerThread::RemoveActiveSampler(this); 656 SamplerThread::RemoveActiveSampler(this);
636 SetActive(false); 657 SetActive(false);
637 } 658 }
638 659
639 void Sampler::SampleStack(TickSample* sample) { 660 void Sampler::SampleStack(TickSample* sample) {
640 StackTracer::Trace(isolate_, sample); 661 StackTracer::Trace(isolate_, sample);
641 if (++samples_taken_ < 0) samples_taken_ = 0; 662 if (++samples_taken_ < 0) samples_taken_ = 0;
642 } 663 }
643 664
644 } } // namespace v8::internal 665 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/log.cc ('k') | src/v8.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698