| 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 |