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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 { | 68 namespace v8 { |
69 namespace internal { | 69 namespace internal { |
70 | 70 |
71 | 71 |
72 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ | 72 #if defined(USE_SIGNALS) |
73 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) | |
74 | 73 |
75 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) | 74 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) |
76 | 75 |
77 // Not all versions of Android's C library provide ucontext_t. | 76 // Not all versions of Android's C library provide ucontext_t. |
78 // Detect this and provide custom but compatible definitions. Note that these | 77 // Detect this and provide custom but compatible definitions. Note that these |
79 // follow the GLibc naming convention to access register values from | 78 // follow the GLibc naming convention to access register values from |
80 // mcontext_t. | 79 // mcontext_t. |
81 // | 80 // |
82 // See http://code.google.com/p/android/issues/detail?id=34784 | 81 // See http://code.google.com/p/android/issues/detail?id=34784 |
83 | 82 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 stack_t uc_stack; | 139 stack_t uc_stack; |
141 mcontext_t uc_mcontext; | 140 mcontext_t uc_mcontext; |
142 // Other fields are not used by V8, don't define them here. | 141 // Other fields are not used by V8, don't define them here. |
143 } ucontext_t; | 142 } ucontext_t; |
144 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; | 143 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; |
145 #endif | 144 #endif |
146 | 145 |
147 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T) | 146 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T) |
148 | 147 |
149 | 148 |
150 static pthread_t GetThreadID() { | |
151 #if defined(__ANDROID__) | |
152 // Android's C library provides gettid(2). | |
153 return gettid(); | |
154 #elif defined(__linux__) | |
155 // Glibc doesn't provide a wrapper for gettid(2). | |
156 return syscall(SYS_gettid); | |
157 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | |
158 || defined(__sun) | |
159 return pthread_self(); | |
160 #endif | |
161 } | |
162 | |
163 | |
164 class Sampler::PlatformData : public Malloced { | 149 class Sampler::PlatformData : public Malloced { |
165 public: | 150 public: |
166 PlatformData() | 151 PlatformData() |
167 : vm_tid_(GetThreadID()), | 152 : vm_tid_(pthread_self()), |
168 vm_tgid_(getpid()), | |
169 profiled_thread_id_(ThreadId::Current()) {} | 153 profiled_thread_id_(ThreadId::Current()) {} |
170 | 154 |
171 pthread_t vm_tid() const { return vm_tid_; } | 155 pthread_t vm_tid() const { return vm_tid_; } |
172 int vm_tgid() const { return vm_tgid_; } | |
173 ThreadId profiled_thread_id() { return profiled_thread_id_; } | 156 ThreadId profiled_thread_id() { return profiled_thread_id_; } |
174 | 157 |
175 private: | 158 private: |
176 pthread_t vm_tid_; | 159 pthread_t vm_tid_; |
177 const int vm_tgid_; | |
178 ThreadId profiled_thread_id_; | 160 ThreadId profiled_thread_id_; |
179 }; | 161 }; |
180 | 162 |
181 | 163 |
182 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { | 164 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
183 #if defined(__native_client__) | 165 #if defined(__native_client__) |
184 // As Native Client does not support signal handling, profiling | 166 // As Native Client does not support signal handling, profiling |
185 // is disabled. | 167 // is disabled. |
186 return; | 168 return; |
187 #else | 169 #else |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { | 415 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { |
434 #if defined(USE_SIGNALS) | 416 #if defined(USE_SIGNALS) |
435 if (!signal_handler_installed_) InstallSignalHandler(); | 417 if (!signal_handler_installed_) InstallSignalHandler(); |
436 #endif | 418 #endif |
437 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); | 419 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); |
438 } else { | 420 } else { |
439 #if defined(USE_SIGNALS) | 421 #if defined(USE_SIGNALS) |
440 if (signal_handler_installed_) RestoreSignalHandler(); | 422 if (signal_handler_installed_) RestoreSignalHandler(); |
441 #endif | 423 #endif |
442 } | 424 } |
443 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough. | 425 OS::Sleep(interval_); |
444 } | 426 } |
445 } | 427 } |
446 | 428 |
447 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { | 429 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { |
448 if (!sampler->isolate()->IsInitialized()) return; | 430 if (!sampler->isolate()->IsInitialized()) return; |
449 if (!sampler->IsProfiling()) return; | 431 if (!sampler->IsProfiling()) return; |
450 SamplerThread* sender = reinterpret_cast<SamplerThread*>(raw_sender); | 432 SamplerThread* sender = reinterpret_cast<SamplerThread*>(raw_sender); |
451 sender->SampleContext(sampler); | 433 sender->SampleContext(sampler); |
452 } | 434 } |
453 | 435 |
454 #if defined(USE_SIGNALS) | 436 #if defined(USE_SIGNALS) |
| 437 |
455 void SampleContext(Sampler* sampler) { | 438 void SampleContext(Sampler* sampler) { |
456 if (!signal_handler_installed_) return; | 439 if (!signal_handler_installed_) return; |
457 Sampler::PlatformData* platform_data = sampler->platform_data(); | 440 pthread_t tid = sampler->platform_data()->vm_tid(); |
458 int tid = platform_data->vm_tid(); | 441 int result = pthread_kill(tid, SIGPROF); |
459 // Glibc doesn't provide a wrapper for tgkill(2). | |
460 #if defined(ANDROID) | |
461 syscall(__NR_tgkill, platform_data->vm_tgid(), tid, SIGPROF); | |
462 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | |
463 || defined(__sun) | |
464 pthread_kill(tid, SIGPROF); | |
465 #else | |
466 int result = syscall(SYS_tgkill, platform_data->vm_tgid(), tid, SIGPROF); | |
467 USE(result); | 442 USE(result); |
468 ASSERT(result == 0); | 443 ASSERT(result == 0); |
469 #endif | |
470 } | |
471 | |
472 void Sleep() { | |
473 // Convert ms to us and subtract 100 us to compensate delays | |
474 // occuring during signal delivery. | |
475 useconds_t interval = interval_ * 1000 - 100; | |
476 #if defined(ANDROID) | |
477 usleep(interval); | |
478 #else | |
479 int result = usleep(interval); | |
480 #ifdef DEBUG | |
481 if (result != 0 && errno != EINTR) { | |
482 fprintf(stderr, | |
483 "SamplerThread usleep error; interval = %u, errno = %d\n", | |
484 interval, | |
485 errno); | |
486 ASSERT(result == 0 || errno == EINTR); | |
487 } | |
488 #endif // DEBUG | |
489 USE(result); | |
490 #endif // ANDROID | |
491 } | 444 } |
492 | 445 |
493 #elif defined(__MACH__) | 446 #elif defined(__MACH__) |
494 | 447 |
495 void SampleContext(Sampler* sampler) { | 448 void SampleContext(Sampler* sampler) { |
496 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); | 449 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); |
497 Isolate* isolate = sampler->isolate(); | 450 Isolate* isolate = sampler->isolate(); |
498 #if defined(USE_SIMULATOR) | 451 #if defined(USE_SIMULATOR) |
499 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS | 452 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS |
500 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); | 453 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); | 507 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); |
555 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); | 508 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); |
556 #endif // USE_SIMULATOR | 509 #endif // USE_SIMULATOR |
557 #undef REGISTER_FIELD | 510 #undef REGISTER_FIELD |
558 sampler->SampleStack(sample); | 511 sampler->SampleStack(sample); |
559 sampler->Tick(sample); | 512 sampler->Tick(sample); |
560 } | 513 } |
561 thread_resume(profiled_thread); | 514 thread_resume(profiled_thread); |
562 } | 515 } |
563 | 516 |
564 void Sleep() { | |
565 OS::Sleep(interval_); | |
566 } | |
567 | |
568 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) | 517 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) |
569 | 518 |
570 void SampleContext(Sampler* sampler) { | 519 void SampleContext(Sampler* sampler) { |
571 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); | 520 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); |
572 if (profiled_thread == NULL) return; | 521 if (profiled_thread == NULL) return; |
573 | 522 |
574 // Context used for sampling the register state of the profiled thread. | 523 // Context used for sampling the register state of the profiled thread. |
575 CONTEXT context; | 524 CONTEXT context; |
576 memset(&context, 0, sizeof(context)); | 525 memset(&context, 0, sizeof(context)); |
577 | 526 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 sample->sp = reinterpret_cast<Address>(context.Esp); | 566 sample->sp = reinterpret_cast<Address>(context.Esp); |
618 sample->fp = reinterpret_cast<Address>(context.Ebp); | 567 sample->fp = reinterpret_cast<Address>(context.Ebp); |
619 #endif | 568 #endif |
620 #endif // USE_SIMULATOR | 569 #endif // USE_SIMULATOR |
621 sampler->SampleStack(sample); | 570 sampler->SampleStack(sample); |
622 sampler->Tick(sample); | 571 sampler->Tick(sample); |
623 } | 572 } |
624 ResumeThread(profiled_thread); | 573 ResumeThread(profiled_thread); |
625 } | 574 } |
626 | 575 |
627 void Sleep() { | |
628 OS::Sleep(interval_); | |
629 } | |
630 | |
631 #endif // USE_SIGNALS | 576 #endif // USE_SIGNALS |
632 | 577 |
633 const int interval_; | 578 const int interval_; |
634 | 579 |
635 // Protects the process wide state below. | 580 // Protects the process wide state below. |
636 static Mutex* mutex_; | 581 static Mutex* mutex_; |
637 static SamplerThread* instance_; | 582 static SamplerThread* instance_; |
638 #if defined(USE_SIGNALS) | 583 #if defined(USE_SIGNALS) |
639 static bool signal_handler_installed_; | 584 static bool signal_handler_installed_; |
640 static struct sigaction old_signal_handler_; | 585 static struct sigaction old_signal_handler_; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 SamplerThread::RemoveActiveSampler(this); | 635 SamplerThread::RemoveActiveSampler(this); |
691 SetActive(false); | 636 SetActive(false); |
692 } | 637 } |
693 | 638 |
694 void Sampler::SampleStack(TickSample* sample) { | 639 void Sampler::SampleStack(TickSample* sample) { |
695 StackTracer::Trace(isolate_, sample); | 640 StackTracer::Trace(isolate_, sample); |
696 if (++samples_taken_ < 0) samples_taken_ = 0; | 641 if (++samples_taken_ < 0) samples_taken_ = 0; |
697 } | 642 } |
698 | 643 |
699 } } // namespace v8::internal | 644 } } // namespace v8::internal |
OLD | NEW |