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

Side by Side Diff: src/platform-linux.cc

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 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
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-macos.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #include <strings.h> // index 51 #include <strings.h> // index
52 #include <errno.h> 52 #include <errno.h>
53 #include <stdarg.h> 53 #include <stdarg.h>
54 54
55 #undef MAP_TYPE 55 #undef MAP_TYPE
56 56
57 #include "v8.h" 57 #include "v8.h"
58 58
59 #include "platform.h" 59 #include "platform.h"
60 #include "v8threads.h" 60 #include "v8threads.h"
61 #include "vm-state-inl.h"
61 62
62 63
63 namespace v8 { 64 namespace v8 {
64 namespace internal { 65 namespace internal {
65 66
66 // 0 is never a valid thread id on Linux since tids and pids share a 67 // 0 is never a valid thread id on Linux since tids and pids share a
67 // name space and pid 0 is reserved (see man 2 kill). 68 // name space and pid 0 is reserved (see man 2 kill).
68 static const pthread_t kNoThread = (pthread_t) 0; 69 static const pthread_t kNoThread = (pthread_t) 0;
69 70
70 71
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 virtual int Lock() { 654 virtual int Lock() {
654 int result = pthread_mutex_lock(&mutex_); 655 int result = pthread_mutex_lock(&mutex_);
655 return result; 656 return result;
656 } 657 }
657 658
658 virtual int Unlock() { 659 virtual int Unlock() {
659 int result = pthread_mutex_unlock(&mutex_); 660 int result = pthread_mutex_unlock(&mutex_);
660 return result; 661 return result;
661 } 662 }
662 663
664 virtual bool TryLock() {
665 int result = pthread_mutex_trylock(&mutex_);
666 // Return false if the lock is busy and locking failed.
667 if (result == EBUSY) {
668 return false;
669 }
670 ASSERT(result == 0); // Verify no other errors.
671 return true;
672 }
673
663 private: 674 private:
664 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 675 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
665 }; 676 };
666 677
667 678
668 Mutex* OS::CreateMutex() { 679 Mutex* OS::CreateMutex() {
669 return new LinuxMutex(); 680 return new LinuxMutex();
670 } 681 }
671 682
672 683
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 } 746 }
736 747
737 748
738 Semaphore* OS::CreateSemaphore(int count) { 749 Semaphore* OS::CreateSemaphore(int count) {
739 return new LinuxSemaphore(count); 750 return new LinuxSemaphore(count);
740 } 751 }
741 752
742 753
743 #ifdef ENABLE_LOGGING_AND_PROFILING 754 #ifdef ENABLE_LOGGING_AND_PROFILING
744 755
745 static Sampler* active_sampler_ = NULL;
746
747
748 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) 756 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
749 // Android runs a fairly new Linux kernel, so signal info is there, 757 // Android runs a fairly new Linux kernel, so signal info is there,
750 // but the C library doesn't have the structs defined. 758 // but the C library doesn't have the structs defined.
751 759
752 struct sigcontext { 760 struct sigcontext {
753 uint32_t trap_no; 761 uint32_t trap_no;
754 uint32_t error_code; 762 uint32_t error_code;
755 uint32_t oldmask; 763 uint32_t oldmask;
756 uint32_t gregs[16]; 764 uint32_t gregs[16];
757 uint32_t arm_cpsr; 765 uint32_t arm_cpsr;
758 uint32_t fault_address; 766 uint32_t fault_address;
759 }; 767 };
760 typedef uint32_t __sigset_t; 768 typedef uint32_t __sigset_t;
761 typedef struct sigcontext mcontext_t; 769 typedef struct sigcontext mcontext_t;
762 typedef struct ucontext { 770 typedef struct ucontext {
763 uint32_t uc_flags; 771 uint32_t uc_flags;
764 struct ucontext* uc_link; 772 struct ucontext* uc_link;
765 stack_t uc_stack; 773 stack_t uc_stack;
766 mcontext_t uc_mcontext; 774 mcontext_t uc_mcontext;
767 __sigset_t uc_sigmask; 775 __sigset_t uc_sigmask;
768 } ucontext_t; 776 } ucontext_t;
769 enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11}; 777 enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
770 778
771 #endif 779 #endif
772 780
773 781
782 static int GetThreadID() {
783 // Glibc doesn't provide a wrapper for gettid(2).
784 return syscall(SYS_gettid);
785 }
786
787
774 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 788 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
775 #ifndef V8_HOST_ARCH_MIPS 789 #ifndef V8_HOST_ARCH_MIPS
776 USE(info); 790 USE(info);
777 if (signal != SIGPROF) return; 791 if (signal != SIGPROF) return;
778 if (active_sampler_ == NULL) return; 792 Isolate* isolate = Isolate::UncheckedCurrent();
793 if (isolate == NULL || !isolate->IsInUse()) return;
794 Sampler* sampler = isolate->logger()->sampler();
795 if (sampler == NULL || !sampler->IsActive()) return;
779 796
780 TickSample sample_obj; 797 TickSample sample_obj;
781 TickSample* sample = CpuProfiler::TickSampleEvent(); 798 TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
782 if (sample == NULL) sample = &sample_obj; 799 if (sample == NULL) sample = &sample_obj;
783 800
784 // We always sample the VM state. 801 // Extracting the sample from the context is extremely machine dependent.
785 sample->state = VMState::current_state(); 802 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
786 803 mcontext_t& mcontext = ucontext->uc_mcontext;
787 // If profiling, we extract the current pc and sp. 804 sample->state = isolate->current_vm_state();
788 if (active_sampler_->IsProfiling()) {
789 // Extracting the sample from the context is extremely machine dependent.
790 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
791 mcontext_t& mcontext = ucontext->uc_mcontext;
792 #if V8_HOST_ARCH_IA32 805 #if V8_HOST_ARCH_IA32
793 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 806 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
794 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 807 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
795 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); 808 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
796 #elif V8_HOST_ARCH_X64 809 #elif V8_HOST_ARCH_X64
797 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); 810 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
798 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); 811 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
799 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); 812 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
800 #elif V8_HOST_ARCH_ARM 813 #elif V8_HOST_ARCH_ARM
801 // An undefined macro evaluates to 0, so this applies to Android's Bionic also. 814 // An undefined macro evaluates to 0, so this applies to Android's Bionic also.
802 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) 815 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
803 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); 816 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
804 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); 817 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
805 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); 818 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
806 #else 819 #else
807 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); 820 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
808 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); 821 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
809 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); 822 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
810 #endif 823 #endif
811 #elif V8_HOST_ARCH_MIPS 824 #elif V8_HOST_ARCH_MIPS
812 // Implement this on MIPS. 825 // Implement this on MIPS.
813 UNIMPLEMENTED(); 826 UNIMPLEMENTED();
814 #endif 827 #endif
815 active_sampler_->SampleStack(sample); 828 sampler->SampleStack(sample);
816 } 829 sampler->Tick(sample);
817
818 active_sampler_->Tick(sample);
819 #endif 830 #endif
820 } 831 }
821 832
822 833
823 class Sampler::PlatformData : public Malloced { 834 class Sampler::PlatformData : public Malloced {
824 public: 835 public:
825 explicit PlatformData(Sampler* sampler) 836 PlatformData() : vm_tid_(GetThreadID()) {}
826 : sampler_(sampler), 837
827 signal_handler_installed_(false), 838 int vm_tid() const { return vm_tid_; }
828 vm_tgid_(getpid()), 839
829 // Glibc doesn't provide a wrapper for gettid(2). 840 private:
830 vm_tid_(syscall(SYS_gettid)), 841 const int vm_tid_;
831 signal_sender_launched_(false) { 842 };
832 } 843
833 844
834 void SignalSender() { 845 class SignalSender : public Thread {
835 while (sampler_->IsActive()) { 846 public:
836 // Glibc doesn't provide a wrapper for tgkill(2). 847 enum SleepInterval {
837 syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF); 848 HALF_INTERVAL,
838 // Convert ms to us and subtract 100 us to compensate delays 849 FULL_INTERVAL
839 // occuring during signal delivery. 850 };
840 const useconds_t interval = sampler_->interval_ * 1000 - 100; 851
841 int result = usleep(interval); 852 explicit SignalSender(int interval)
853 : Thread(NULL), vm_tgid_(getpid()), interval_(interval) {}
854
855 static void AddActiveSampler(Sampler* sampler) {
856 ScopedLock lock(mutex_);
857 SamplerRegistry::AddActiveSampler(sampler);
858 if (instance_ == NULL) {
859 // Install a signal handler.
860 struct sigaction sa;
861 sa.sa_sigaction = ProfilerSignalHandler;
862 sigemptyset(&sa.sa_mask);
863 sa.sa_flags = SA_RESTART | SA_SIGINFO;
864 signal_handler_installed_ =
865 (sigaction(SIGPROF, &sa, &old_signal_handler_) != 0);
866
867 // Start a thread that sends SIGPROF signal to VM threads.
868 instance_ = new SignalSender(sampler->interval());
869 instance_->Start();
870 } else {
871 ASSERT(instance_->interval_ == sampler->interval());
872 }
873 }
874
875 static void RemoveActiveSampler(Sampler* sampler) {
876 ScopedLock lock(mutex_);
877 SamplerRegistry::RemoveActiveSampler(sampler);
878 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
879 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
880 instance_->Join();
881 delete instance_;
882 instance_ = NULL;
883
884 // Restore the old signal handler.
885 if (signal_handler_installed_) {
886 sigaction(SIGPROF, &old_signal_handler_, 0);
887 signal_handler_installed_ = false;
888 }
889 }
890 }
891
892 // Implement Thread::Run().
893 virtual void Run() {
894 SamplerRegistry::State state = SamplerRegistry::GetState();
895 while (state != SamplerRegistry::HAS_NO_SAMPLERS) {
896 bool cpu_profiling_enabled =
897 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
898 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
899 // When CPU profiling is enabled both JavaScript and C++ code is
900 // profiled. We must not suspend.
901 if (!cpu_profiling_enabled) {
902 if (rate_limiter_.SuspendIfNecessary()) continue;
903 }
904 if (cpu_profiling_enabled && runtime_profiler_enabled) {
905 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
906 return;
907 }
908 Sleep(HALF_INTERVAL);
909 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
910 return;
911 }
912 Sleep(HALF_INTERVAL);
913 } else {
914 if (cpu_profiling_enabled) {
915 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
916 this)) {
917 return;
918 }
919 }
920 if (runtime_profiler_enabled) {
921 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
922 NULL)) {
923 return;
924 }
925 }
926 Sleep(FULL_INTERVAL);
927 }
928 }
929 }
930
931 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
932 if (!sampler->IsProfiling()) return;
933 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
934 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
935 }
936
937 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
938 if (!sampler->isolate()->IsInitialized()) return;
939 sampler->isolate()->runtime_profiler()->NotifyTick();
940 }
941
942 void SendProfilingSignal(int tid) {
943 // Glibc doesn't provide a wrapper for tgkill(2).
944 syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
945 }
946
947 void Sleep(SleepInterval full_or_half) {
948 // Convert ms to us and subtract 100 us to compensate delays
949 // occuring during signal delivery.
950 useconds_t interval = interval_ * 1000 - 100;
951 if (full_or_half == HALF_INTERVAL) interval /= 2;
952 int result = usleep(interval);
842 #ifdef DEBUG 953 #ifdef DEBUG
843 if (result != 0 && errno != EINTR) { 954 if (result != 0 && errno != EINTR) {
844 fprintf(stderr, 955 fprintf(stderr,
845 "SignalSender usleep error; interval = %u, errno = %d\n", 956 "SignalSender usleep error; interval = %u, errno = %d\n",
846 interval, 957 interval,
847 errno); 958 errno);
848 ASSERT(result == 0 || errno == EINTR); 959 ASSERT(result == 0 || errno == EINTR);
849 } 960 }
850 #endif 961 #endif
851 USE(result); 962 USE(result);
852 } 963 }
853 } 964
854 965 const int vm_tgid_;
855 Sampler* sampler_; 966 const int interval_;
856 bool signal_handler_installed_; 967 RuntimeProfilerRateLimiter rate_limiter_;
857 struct sigaction old_signal_handler_; 968
858 int vm_tgid_; 969 // Protects the process wide state below.
859 int vm_tid_; 970 static Mutex* mutex_;
860 bool signal_sender_launched_; 971 static SignalSender* instance_;
861 pthread_t signal_sender_thread_; 972 static bool signal_handler_installed_;
973 static struct sigaction old_signal_handler_;
974
975 DISALLOW_COPY_AND_ASSIGN(SignalSender);
862 }; 976 };
863 977
864 978
865 static void* SenderEntry(void* arg) { 979 Mutex* SignalSender::mutex_ = OS::CreateMutex();
866 Sampler::PlatformData* data = 980 SignalSender* SignalSender::instance_ = NULL;
867 reinterpret_cast<Sampler::PlatformData*>(arg); 981 struct sigaction SignalSender::old_signal_handler_;
868 data->SignalSender(); 982 bool SignalSender::signal_handler_installed_ = false;
869 return 0; 983
870 } 984
871 985 Sampler::Sampler(Isolate* isolate, int interval)
872
873 Sampler::Sampler(Isolate* isolate, int interval, bool profiling)
874 : isolate_(isolate), 986 : isolate_(isolate),
875 interval_(interval), 987 interval_(interval),
876 synchronous_(profiling), 988 profiling_(false),
877 profiling_(profiling),
878 active_(false), 989 active_(false),
879 samples_taken_(0) { 990 samples_taken_(0) {
880 data_ = new PlatformData(this); 991 data_ = new PlatformData;
881 } 992 }
882 993
883 994
884 Sampler::~Sampler() { 995 Sampler::~Sampler() {
885 ASSERT(!data_->signal_sender_launched_); 996 ASSERT(!IsActive());
886 delete data_; 997 delete data_;
887 } 998 }
888 999
889 1000
890 void Sampler::Start() { 1001 void Sampler::Start() {
891 // There can only be one active sampler at the time on POSIX 1002 ASSERT(!IsActive());
892 // platforms. 1003 SetActive(true);
893 if (active_sampler_ != NULL) return; 1004 SignalSender::AddActiveSampler(this);
894
895 // Request profiling signals.
896 struct sigaction sa;
897 sa.sa_sigaction = ProfilerSignalHandler;
898 sigemptyset(&sa.sa_mask);
899 sa.sa_flags = SA_RESTART | SA_SIGINFO;
900 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
901 data_->signal_handler_installed_ = true;
902
903 // Start a thread that sends SIGPROF signal to VM thread.
904 // Sending the signal ourselves instead of relying on itimer provides
905 // much better accuracy.
906 active_ = true;
907 if (pthread_create(
908 &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
909 data_->signal_sender_launched_ = true;
910 }
911
912 // Set this sampler as the active sampler.
913 active_sampler_ = this;
914 } 1005 }
915 1006
916 1007
917 void Sampler::Stop() { 1008 void Sampler::Stop() {
918 active_ = false; 1009 ASSERT(IsActive());
919 1010 SignalSender::RemoveActiveSampler(this);
920 // Wait for signal sender termination (it will exit after setting 1011 SetActive(false);
921 // active_ to false). 1012 }
922 if (data_->signal_sender_launched_) {
923 pthread_join(data_->signal_sender_thread_, NULL);
924 data_->signal_sender_launched_ = false;
925 }
926
927 // Restore old signal handler
928 if (data_->signal_handler_installed_) {
929 sigaction(SIGPROF, &data_->old_signal_handler_, 0);
930 data_->signal_handler_installed_ = false;
931 }
932
933 // This sampler is no longer the active sampler.
934 active_sampler_ = NULL;
935 }
936
937 1013
938 #endif // ENABLE_LOGGING_AND_PROFILING 1014 #endif // ENABLE_LOGGING_AND_PROFILING
939 1015
940 } } // namespace v8::internal 1016 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698