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

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

Issue 11065034: Rollback trunk to bleeding_edge revision 12524 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 2 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/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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 switch (feature) { 141 switch (feature) {
142 case VFP2: 142 case VFP2:
143 search_string = "vfp"; 143 search_string = "vfp";
144 break; 144 break;
145 case VFP3: 145 case VFP3:
146 search_string = "vfpv3"; 146 search_string = "vfpv3";
147 break; 147 break;
148 case ARMv7: 148 case ARMv7:
149 search_string = "ARMv7"; 149 search_string = "ARMv7";
150 break; 150 break;
151 case SUDIV:
152 search_string = "idiva";
153 break;
151 default: 154 default:
152 UNREACHABLE(); 155 UNREACHABLE();
153 } 156 }
154 157
155 if (CPUInfoContainsString(search_string)) { 158 if (CPUInfoContainsString(search_string)) {
156 return true; 159 return true;
157 } 160 }
158 161
159 if (feature == VFP3) { 162 if (feature == VFP3) {
160 // Some old kernels will report vfp not vfpv3. Here we make a last attempt 163 // Some old kernels will report vfp not vfpv3. Here we make a last attempt
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 return; 1008 return;
1006 } 1009 }
1007 if (v8::Locker::IsActive() && 1010 if (v8::Locker::IsActive() &&
1008 !isolate->thread_manager()->IsLockedByCurrentThread()) { 1011 !isolate->thread_manager()->IsLockedByCurrentThread()) {
1009 return; 1012 return;
1010 } 1013 }
1011 1014
1012 Sampler* sampler = isolate->logger()->sampler(); 1015 Sampler* sampler = isolate->logger()->sampler();
1013 if (sampler == NULL || !sampler->IsActive()) return; 1016 if (sampler == NULL || !sampler->IsActive()) return;
1014 1017
1015 TickSample sample_obj; 1018 TickSample* sample = CpuProfiler::StartTickSampleEvent(isolate);
1016 TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 1019 if (sample == NULL) return;
1017 if (sample == NULL) sample = &sample_obj;
1018 1020
1019 // Extracting the sample from the context is extremely machine dependent. 1021 // Extracting the sample from the context is extremely machine dependent.
1020 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 1022 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
1021 mcontext_t& mcontext = ucontext->uc_mcontext; 1023 mcontext_t& mcontext = ucontext->uc_mcontext;
1022 sample->state = isolate->current_vm_state(); 1024 sample->state = isolate->current_vm_state();
1023 #if V8_HOST_ARCH_IA32 1025 #if V8_HOST_ARCH_IA32
1024 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 1026 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
1025 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 1027 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
1026 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); 1028 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
1027 #elif V8_HOST_ARCH_X64 1029 #elif V8_HOST_ARCH_X64
(...skipping 14 matching lines...) Expand all
1042 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); 1044 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
1043 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && 1045 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
1044 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) 1046 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1045 #elif V8_HOST_ARCH_MIPS 1047 #elif V8_HOST_ARCH_MIPS
1046 sample->pc = reinterpret_cast<Address>(mcontext.pc); 1048 sample->pc = reinterpret_cast<Address>(mcontext.pc);
1047 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); 1049 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
1048 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); 1050 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
1049 #endif // V8_HOST_ARCH_* 1051 #endif // V8_HOST_ARCH_*
1050 sampler->SampleStack(sample); 1052 sampler->SampleStack(sample);
1051 sampler->Tick(sample); 1053 sampler->Tick(sample);
1054 CpuProfiler::FinishTickSampleEvent(isolate);
1052 } 1055 }
1053 1056
1054 1057
1058 class CpuProfilerSignalHandler {
1059 public:
1060 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1061 static void TearDown() { delete mutex_; }
1062
1063 static void InstallSignalHandler() {
1064 struct sigaction sa;
1065 ScopedLock lock(mutex_);
1066 if (signal_handler_installed_counter_ > 0) {
1067 signal_handler_installed_counter_++;
1068 return;
1069 }
1070 sa.sa_sigaction = ProfilerSignalHandler;
1071 sigemptyset(&sa.sa_mask);
1072 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1073 if (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0) {
1074 signal_handler_installed_counter_++;
1075 }
1076 }
1077
1078 static void RestoreSignalHandler() {
1079 ScopedLock lock(mutex_);
1080 if (signal_handler_installed_counter_ == 0)
1081 return;
1082 if (signal_handler_installed_counter_ == 1) {
1083 sigaction(SIGPROF, &old_signal_handler_, 0);
1084 }
1085 signal_handler_installed_counter_--;
1086 }
1087
1088 static bool signal_handler_installed() {
1089 return signal_handler_installed_counter_ > 0;
1090 }
1091
1092 private:
1093 static int signal_handler_installed_counter_;
1094 static struct sigaction old_signal_handler_;
1095 static Mutex* mutex_;
1096 };
1097
1098
1099 int CpuProfilerSignalHandler::signal_handler_installed_counter_ = 0;
1100 struct sigaction CpuProfilerSignalHandler::old_signal_handler_;
1101 Mutex* CpuProfilerSignalHandler::mutex_ = NULL;
1102
1103
1055 class Sampler::PlatformData : public Malloced { 1104 class Sampler::PlatformData : public Malloced {
1056 public: 1105 public:
1057 PlatformData() : vm_tid_(GetThreadID()) {} 1106 PlatformData()
1107 : vm_tgid_(getpid()),
1108 vm_tid_(GetThreadID()) {}
1058 1109
1059 int vm_tid() const { return vm_tid_; } 1110 void SendProfilingSignal() {
1111 if (!CpuProfilerSignalHandler::signal_handler_installed()) return;
1112 // Glibc doesn't provide a wrapper for tgkill(2).
1113 #if defined(ANDROID)
1114 syscall(__NR_tgkill, vm_tgid_, vm_tid_, SIGPROF);
1115 #else
1116 syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
1117 #endif
1118 }
1060 1119
1061 private: 1120 private:
1121 const int vm_tgid_;
1062 const int vm_tid_; 1122 const int vm_tid_;
1063 }; 1123 };
1064 1124
1065 1125
1066 class SignalSender : public Thread { 1126 class SignalSender : public Thread {
1067 public: 1127 public:
1068 enum SleepInterval { 1128 enum SleepInterval {
1069 HALF_INTERVAL, 1129 HALF_INTERVAL,
1070 FULL_INTERVAL 1130 FULL_INTERVAL
1071 }; 1131 };
1072 1132
1073 static const int kSignalSenderStackSize = 64 * KB; 1133 static const int kSignalSenderStackSize = 64 * KB;
1074 1134
1075 explicit SignalSender(int interval) 1135 explicit SignalSender(int interval)
1076 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), 1136 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
1077 vm_tgid_(getpid()),
1078 interval_(interval) {} 1137 interval_(interval) {}
1079 1138
1080 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } 1139 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1081 static void TearDown() { delete mutex_; } 1140 static void TearDown() { delete mutex_; }
1082 1141
1083 static void InstallSignalHandler() {
1084 struct sigaction sa;
1085 sa.sa_sigaction = ProfilerSignalHandler;
1086 sigemptyset(&sa.sa_mask);
1087 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1088 signal_handler_installed_ =
1089 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
1090 }
1091
1092 static void RestoreSignalHandler() {
1093 if (signal_handler_installed_) {
1094 sigaction(SIGPROF, &old_signal_handler_, 0);
1095 signal_handler_installed_ = false;
1096 }
1097 }
1098
1099 static void AddActiveSampler(Sampler* sampler) { 1142 static void AddActiveSampler(Sampler* sampler) {
1100 ScopedLock lock(mutex_); 1143 ScopedLock lock(mutex_);
1101 SamplerRegistry::AddActiveSampler(sampler); 1144 SamplerRegistry::AddActiveSampler(sampler);
1102 if (instance_ == NULL) { 1145 if (instance_ == NULL) {
1103 // Start a thread that will send SIGPROF signal to VM threads, 1146 // Start a thread that will send SIGPROF signal to VM threads,
1104 // when CPU profiling will be enabled. 1147 // when CPU profiling will be enabled.
1105 instance_ = new SignalSender(sampler->interval()); 1148 instance_ = new SignalSender(sampler->interval());
1106 instance_->Start(); 1149 instance_->Start();
1107 } else { 1150 } else {
1108 ASSERT(instance_->interval_ == sampler->interval()); 1151 ASSERT(instance_->interval_ == sampler->interval());
1109 } 1152 }
1110 } 1153 }
1111 1154
1112 static void RemoveActiveSampler(Sampler* sampler) { 1155 static void RemoveActiveSampler(Sampler* sampler) {
1113 ScopedLock lock(mutex_); 1156 ScopedLock lock(mutex_);
1114 SamplerRegistry::RemoveActiveSampler(sampler); 1157 SamplerRegistry::RemoveActiveSampler(sampler);
1115 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 1158 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
1116 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 1159 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
1117 delete instance_; 1160 delete instance_;
1118 instance_ = NULL; 1161 instance_ = NULL;
1119 RestoreSignalHandler();
1120 } 1162 }
1121 } 1163 }
1122 1164
1123 // Implement Thread::Run(). 1165 // Implement Thread::Run().
1124 virtual void Run() { 1166 virtual void Run() {
1125 SamplerRegistry::State state; 1167 SamplerRegistry::State state;
1126 while ((state = SamplerRegistry::GetState()) != 1168 while ((state = SamplerRegistry::GetState()) !=
1127 SamplerRegistry::HAS_NO_SAMPLERS) { 1169 SamplerRegistry::HAS_NO_SAMPLERS) {
1128 bool cpu_profiling_enabled = 1170 if (rate_limiter_.SuspendIfNecessary()) continue;
1129 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 1171 if (RuntimeProfiler::IsEnabled()) {
1130 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
1131 if (cpu_profiling_enabled && !signal_handler_installed_) {
1132 InstallSignalHandler();
1133 } else if (!cpu_profiling_enabled && signal_handler_installed_) {
1134 RestoreSignalHandler();
1135 }
1136 // When CPU profiling is enabled both JavaScript and C++ code is
1137 // profiled. We must not suspend.
1138 if (!cpu_profiling_enabled) {
1139 if (rate_limiter_.SuspendIfNecessary()) continue;
1140 }
1141 if (cpu_profiling_enabled && runtime_profiler_enabled) {
1142 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
1143 return;
1144 }
1145 Sleep(HALF_INTERVAL);
1146 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 1172 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
1147 return; 1173 return;
1148 } 1174 }
1149 Sleep(HALF_INTERVAL);
1150 } else {
1151 if (cpu_profiling_enabled) {
1152 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
1153 this)) {
1154 return;
1155 }
1156 }
1157 if (runtime_profiler_enabled) {
1158 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
1159 NULL)) {
1160 return;
1161 }
1162 }
1163 Sleep(FULL_INTERVAL);
1164 } 1175 }
1176 Sleep(FULL_INTERVAL);
1165 } 1177 }
1166 } 1178 }
1167 1179
1168 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
1169 if (!sampler->IsProfiling()) return;
1170 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
1171 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
1172 }
1173
1174 static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 1180 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
1175 if (!sampler->isolate()->IsInitialized()) return; 1181 if (!sampler->isolate()->IsInitialized()) return;
1176 sampler->isolate()->runtime_profiler()->NotifyTick(); 1182 sampler->isolate()->runtime_profiler()->NotifyTick();
1177 } 1183 }
1178 1184
1179 void SendProfilingSignal(int tid) {
1180 if (!signal_handler_installed_) return;
1181 // Glibc doesn't provide a wrapper for tgkill(2).
1182 #if defined(ANDROID)
1183 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
1184 #else
1185 syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
1186 #endif
1187 }
1188
1189 void Sleep(SleepInterval full_or_half) { 1185 void Sleep(SleepInterval full_or_half) {
1190 // Convert ms to us and subtract 100 us to compensate delays 1186 // Convert ms to us and subtract 100 us to compensate delays
1191 // occuring during signal delivery. 1187 // occuring during signal delivery.
1192 useconds_t interval = interval_ * 1000 - 100; 1188 useconds_t interval = interval_ * 1000 - 100;
1193 if (full_or_half == HALF_INTERVAL) interval /= 2; 1189 if (full_or_half == HALF_INTERVAL) interval /= 2;
1194 #if defined(ANDROID) 1190 #if defined(ANDROID)
1195 usleep(interval); 1191 usleep(interval);
1196 #else 1192 #else
1197 int result = usleep(interval); 1193 int result = usleep(interval);
1198 #ifdef DEBUG 1194 #ifdef DEBUG
1199 if (result != 0 && errno != EINTR) { 1195 if (result != 0 && errno != EINTR) {
1200 fprintf(stderr, 1196 fprintf(stderr,
1201 "SignalSender usleep error; interval = %u, errno = %d\n", 1197 "SignalSender usleep error; interval = %u, errno = %d\n",
1202 interval, 1198 interval,
1203 errno); 1199 errno);
1204 ASSERT(result == 0 || errno == EINTR); 1200 ASSERT(result == 0 || errno == EINTR);
1205 } 1201 }
1206 #endif // DEBUG 1202 #endif // DEBUG
1207 USE(result); 1203 USE(result);
1208 #endif // ANDROID 1204 #endif // ANDROID
1209 } 1205 }
1210 1206
1211 const int vm_tgid_;
1212 const int interval_; 1207 const int interval_;
1213 RuntimeProfilerRateLimiter rate_limiter_; 1208 RuntimeProfilerRateLimiter rate_limiter_;
1214 1209
1215 // Protects the process wide state below. 1210 // Protects the process wide state below.
1216 static Mutex* mutex_; 1211 static Mutex* mutex_;
1217 static SignalSender* instance_; 1212 static SignalSender* instance_;
1218 static bool signal_handler_installed_;
1219 static struct sigaction old_signal_handler_;
1220 1213
1221 private: 1214 private:
1222 DISALLOW_COPY_AND_ASSIGN(SignalSender); 1215 DISALLOW_COPY_AND_ASSIGN(SignalSender);
1223 }; 1216 };
1224 1217
1225 1218
1226 Mutex* SignalSender::mutex_ = NULL; 1219 Mutex* SignalSender::mutex_ = NULL;
1227 SignalSender* SignalSender::instance_ = NULL; 1220 SignalSender* SignalSender::instance_ = NULL;
1228 struct sigaction SignalSender::old_signal_handler_;
1229 bool SignalSender::signal_handler_installed_ = false;
1230 1221
1231 1222
1232 void OS::SetUp() { 1223 void OS::SetUp() {
1233 // Seed the random number generator. We preserve microsecond resolution. 1224 // Seed the random number generator. We preserve microsecond resolution.
1234 uint64_t seed = Ticks() ^ (getpid() << 16); 1225 uint64_t seed = Ticks() ^ (getpid() << 16);
1235 srandom(static_cast<unsigned int>(seed)); 1226 srandom(static_cast<unsigned int>(seed));
1236 limit_mutex = CreateMutex(); 1227 limit_mutex = CreateMutex();
1237 1228
1238 #ifdef __arm__ 1229 #ifdef __arm__
1239 // When running on ARM hardware check that the EABI used by V8 and 1230 // When running on ARM hardware check that the EABI used by V8 and
1240 // by the C code is the same. 1231 // by the C code is the same.
1241 bool hard_float = OS::ArmUsingHardFloat(); 1232 bool hard_float = OS::ArmUsingHardFloat();
1242 if (hard_float) { 1233 if (hard_float) {
1243 #if !USE_EABI_HARDFLOAT 1234 #if !USE_EABI_HARDFLOAT
1244 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " 1235 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without "
1245 "-DUSE_EABI_HARDFLOAT\n"); 1236 "-DUSE_EABI_HARDFLOAT\n");
1246 exit(1); 1237 exit(1);
1247 #endif 1238 #endif
1248 } else { 1239 } else {
1249 #if USE_EABI_HARDFLOAT 1240 #if USE_EABI_HARDFLOAT
1250 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " 1241 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with "
1251 "-DUSE_EABI_HARDFLOAT\n"); 1242 "-DUSE_EABI_HARDFLOAT\n");
1252 exit(1); 1243 exit(1);
1253 #endif 1244 #endif
1254 } 1245 }
1255 #endif 1246 #endif
1256 SignalSender::SetUp(); 1247 SignalSender::SetUp();
1248 CpuProfilerSignalHandler::SetUp();
1257 } 1249 }
1258 1250
1259 1251
1260 void OS::TearDown() { 1252 void OS::TearDown() {
1261 SignalSender::TearDown(); 1253 SignalSender::TearDown();
1254 CpuProfilerSignalHandler::TearDown();
1262 delete limit_mutex; 1255 delete limit_mutex;
1263 } 1256 }
1264 1257
1265 1258
1266 Sampler::Sampler(Isolate* isolate, int interval) 1259 Sampler::Sampler(Isolate* isolate, int interval)
1267 : isolate_(isolate), 1260 : isolate_(isolate),
1268 interval_(interval), 1261 interval_(interval),
1269 profiling_(false), 1262 profiling_(false),
1270 active_(false), 1263 active_(false),
1271 samples_taken_(0) { 1264 samples_taken_(0) {
1272 data_ = new PlatformData; 1265 data_ = new PlatformData;
1273 } 1266 }
1274 1267
1275 1268
1276 Sampler::~Sampler() { 1269 Sampler::~Sampler() {
1277 ASSERT(!IsActive()); 1270 ASSERT(!IsActive());
1278 delete data_; 1271 delete data_;
1279 } 1272 }
1280 1273
1281 1274
1275 void Sampler::DoSample() {
1276 platform_data()->SendProfilingSignal();
1277 }
1278
1279
1282 void Sampler::Start() { 1280 void Sampler::Start() {
1283 ASSERT(!IsActive()); 1281 ASSERT(!IsActive());
1282 CpuProfilerSignalHandler::InstallSignalHandler();
1284 SetActive(true); 1283 SetActive(true);
1285 SignalSender::AddActiveSampler(this); 1284 SignalSender::AddActiveSampler(this);
1286 } 1285 }
1287 1286
1288 1287
1289 void Sampler::Stop() { 1288 void Sampler::Stop() {
1290 ASSERT(IsActive()); 1289 ASSERT(IsActive());
1290 CpuProfilerSignalHandler::RestoreSignalHandler();
1291 SignalSender::RemoveActiveSampler(this); 1291 SignalSender::RemoveActiveSampler(this);
1292 SetActive(false); 1292 SetActive(false);
1293 } 1293 }
1294 1294
1295 1295
1296 } } // namespace v8::internal 1296 } } // 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