| OLD | NEW |
| 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 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 #elif V8_HOST_ARCH_MIPS | 1120 #elif V8_HOST_ARCH_MIPS |
| 1121 sample->pc = reinterpret_cast<Address>(mcontext.pc); | 1121 sample->pc = reinterpret_cast<Address>(mcontext.pc); |
| 1122 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); | 1122 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
| 1123 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); | 1123 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
| 1124 #endif // V8_HOST_ARCH_* | 1124 #endif // V8_HOST_ARCH_* |
| 1125 sampler->SampleStack(sample); | 1125 sampler->SampleStack(sample); |
| 1126 sampler->Tick(sample); | 1126 sampler->Tick(sample); |
| 1127 } | 1127 } |
| 1128 | 1128 |
| 1129 | 1129 |
| 1130 class CpuProfilerSignalHandler { | |
| 1131 public: | |
| 1132 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } | |
| 1133 static void TearDown() { delete mutex_; } | |
| 1134 | |
| 1135 static bool RegisterProfilingSampler() { | |
| 1136 ScopedLock lock(mutex_); | |
| 1137 if (!profiling_samplers_count_) InstallSignalHandler(); | |
| 1138 ++profiling_samplers_count_; | |
| 1139 return signal_handler_installed_; | |
| 1140 } | |
| 1141 | |
| 1142 static void UnregisterProfilingSampler() { | |
| 1143 ScopedLock lock(mutex_); | |
| 1144 ASSERT(profiling_samplers_count_ > 0); | |
| 1145 if (!profiling_samplers_count_) return; | |
| 1146 if (profiling_samplers_count_ == 1) RestoreSignalHandler(); | |
| 1147 --profiling_samplers_count_; | |
| 1148 } | |
| 1149 | |
| 1150 private: | |
| 1151 static void InstallSignalHandler() { | |
| 1152 struct sigaction sa; | |
| 1153 sa.sa_sigaction = ProfilerSignalHandler; | |
| 1154 sigemptyset(&sa.sa_mask); | |
| 1155 sa.sa_flags = SA_RESTART | SA_SIGINFO; | |
| 1156 signal_handler_installed_ = | |
| 1157 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); | |
| 1158 } | |
| 1159 | |
| 1160 static void RestoreSignalHandler() { | |
| 1161 if (signal_handler_installed_) { | |
| 1162 sigaction(SIGPROF, &old_signal_handler_, 0); | |
| 1163 signal_handler_installed_ = false; | |
| 1164 } | |
| 1165 } | |
| 1166 | |
| 1167 // Protects the process wide state below. | |
| 1168 static Mutex* mutex_; | |
| 1169 static int profiling_samplers_count_; | |
| 1170 static bool signal_handler_installed_; | |
| 1171 static struct sigaction old_signal_handler_; | |
| 1172 }; | |
| 1173 | |
| 1174 | |
| 1175 Mutex* CpuProfilerSignalHandler::mutex_ = NULL; | |
| 1176 int CpuProfilerSignalHandler::profiling_samplers_count_ = 0; | |
| 1177 bool CpuProfilerSignalHandler::signal_handler_installed_ = false; | |
| 1178 struct sigaction CpuProfilerSignalHandler::old_signal_handler_; | |
| 1179 | |
| 1180 | |
| 1181 class Sampler::PlatformData : public Malloced { | 1130 class Sampler::PlatformData : public Malloced { |
| 1182 public: | 1131 public: |
| 1183 PlatformData() | 1132 PlatformData() : vm_tid_(GetThreadID()) {} |
| 1184 : vm_tgid_(getpid()), | |
| 1185 vm_tid_(GetThreadID()), | |
| 1186 signal_handler_installed_(false) {} | |
| 1187 | 1133 |
| 1188 void set_signal_handler_installed(bool value) { | 1134 int vm_tid() const { return vm_tid_; } |
| 1189 signal_handler_installed_ = value; | |
| 1190 } | |
| 1191 | |
| 1192 void SendProfilingSignal() { | |
| 1193 if (!signal_handler_installed_) return; | |
| 1194 // Glibc doesn't provide a wrapper for tgkill(2). | |
| 1195 #if defined(ANDROID) | |
| 1196 syscall(__NR_tgkill, vm_tgid_, vm_tid_, SIGPROF); | |
| 1197 #else | |
| 1198 int result = syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF); | |
| 1199 USE(result); | |
| 1200 ASSERT(result == 0); | |
| 1201 #endif | |
| 1202 } | |
| 1203 | 1135 |
| 1204 private: | 1136 private: |
| 1205 const int vm_tgid_; | |
| 1206 const int vm_tid_; | 1137 const int vm_tid_; |
| 1207 bool signal_handler_installed_; | |
| 1208 }; | 1138 }; |
| 1209 | 1139 |
| 1210 | 1140 |
| 1211 class SignalSender : public Thread { | 1141 class SignalSender : public Thread { |
| 1212 public: | 1142 public: |
| 1213 static const int kSignalSenderStackSize = 64 * KB; | 1143 static const int kSignalSenderStackSize = 64 * KB; |
| 1214 | 1144 |
| 1215 explicit SignalSender(int interval) | 1145 explicit SignalSender(int interval) |
| 1216 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), | 1146 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), |
| 1147 vm_tgid_(getpid()), |
| 1217 interval_(interval) {} | 1148 interval_(interval) {} |
| 1218 | 1149 |
| 1219 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } | 1150 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } |
| 1220 static void TearDown() { delete mutex_; } | 1151 static void TearDown() { delete mutex_; } |
| 1221 | 1152 |
| 1153 static void InstallSignalHandler() { |
| 1154 struct sigaction sa; |
| 1155 sa.sa_sigaction = ProfilerSignalHandler; |
| 1156 sigemptyset(&sa.sa_mask); |
| 1157 sa.sa_flags = SA_RESTART | SA_SIGINFO; |
| 1158 signal_handler_installed_ = |
| 1159 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
| 1160 } |
| 1161 |
| 1162 static void RestoreSignalHandler() { |
| 1163 if (signal_handler_installed_) { |
| 1164 sigaction(SIGPROF, &old_signal_handler_, 0); |
| 1165 signal_handler_installed_ = false; |
| 1166 } |
| 1167 } |
| 1168 |
| 1222 static void AddActiveSampler(Sampler* sampler) { | 1169 static void AddActiveSampler(Sampler* sampler) { |
| 1223 ScopedLock lock(mutex_); | 1170 ScopedLock lock(mutex_); |
| 1224 SamplerRegistry::AddActiveSampler(sampler); | 1171 SamplerRegistry::AddActiveSampler(sampler); |
| 1225 if (instance_ == NULL) { | 1172 if (instance_ == NULL) { |
| 1226 // Start a thread that will send SIGPROF signal to VM threads, | 1173 // Start a thread that will send SIGPROF signal to VM threads, |
| 1227 // when CPU profiling will be enabled. | 1174 // when CPU profiling will be enabled. |
| 1228 instance_ = new SignalSender(sampler->interval()); | 1175 instance_ = new SignalSender(sampler->interval()); |
| 1229 instance_->Start(); | 1176 instance_->Start(); |
| 1230 } else { | 1177 } else { |
| 1231 ASSERT(instance_->interval_ == sampler->interval()); | 1178 ASSERT(instance_->interval_ == sampler->interval()); |
| 1232 } | 1179 } |
| 1233 } | 1180 } |
| 1234 | 1181 |
| 1235 static void RemoveActiveSampler(Sampler* sampler) { | 1182 static void RemoveActiveSampler(Sampler* sampler) { |
| 1236 ScopedLock lock(mutex_); | 1183 ScopedLock lock(mutex_); |
| 1237 SamplerRegistry::RemoveActiveSampler(sampler); | 1184 SamplerRegistry::RemoveActiveSampler(sampler); |
| 1238 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { | 1185 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { |
| 1239 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); | 1186 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); |
| 1240 delete instance_; | 1187 delete instance_; |
| 1241 instance_ = NULL; | 1188 instance_ = NULL; |
| 1189 RestoreSignalHandler(); |
| 1242 } | 1190 } |
| 1243 } | 1191 } |
| 1244 | 1192 |
| 1245 // Implement Thread::Run(). | 1193 // Implement Thread::Run(). |
| 1246 virtual void Run() { | 1194 virtual void Run() { |
| 1247 SamplerRegistry::State state; | 1195 SamplerRegistry::State state; |
| 1248 while ((state = SamplerRegistry::GetState()) != | 1196 while ((state = SamplerRegistry::GetState()) != |
| 1249 SamplerRegistry::HAS_NO_SAMPLERS) { | 1197 SamplerRegistry::HAS_NO_SAMPLERS) { |
| 1250 // When CPU profiling is enabled both JavaScript and C++ code is | 1198 // When CPU profiling is enabled both JavaScript and C++ code is |
| 1251 // profiled. We must not suspend. | 1199 // profiled. We must not suspend. |
| 1252 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { | 1200 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { |
| 1201 if (!signal_handler_installed_) InstallSignalHandler(); |
| 1253 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); | 1202 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); |
| 1254 } else { | 1203 } else { |
| 1204 if (signal_handler_installed_) RestoreSignalHandler(); |
| 1255 if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue; | 1205 if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue; |
| 1256 } | 1206 } |
| 1257 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough. | 1207 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough. |
| 1258 } | 1208 } |
| 1259 } | 1209 } |
| 1260 | 1210 |
| 1261 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { | 1211 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { |
| 1262 if (!sampler->IsProfiling()) return; | 1212 if (!sampler->IsProfiling()) return; |
| 1263 sampler->DoSample(); | 1213 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); |
| 1214 sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); |
| 1215 } |
| 1216 |
| 1217 void SendProfilingSignal(int tid) { |
| 1218 if (!signal_handler_installed_) return; |
| 1219 // Glibc doesn't provide a wrapper for tgkill(2). |
| 1220 #if defined(ANDROID) |
| 1221 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF); |
| 1222 #else |
| 1223 int result = syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF); |
| 1224 USE(result); |
| 1225 ASSERT(result == 0); |
| 1226 #endif |
| 1264 } | 1227 } |
| 1265 | 1228 |
| 1266 void Sleep() { | 1229 void Sleep() { |
| 1267 // Convert ms to us and subtract 100 us to compensate delays | 1230 // Convert ms to us and subtract 100 us to compensate delays |
| 1268 // occuring during signal delivery. | 1231 // occuring during signal delivery. |
| 1269 useconds_t interval = interval_ * 1000 - 100; | 1232 useconds_t interval = interval_ * 1000 - 100; |
| 1270 #if defined(ANDROID) | 1233 #if defined(ANDROID) |
| 1271 usleep(interval); | 1234 usleep(interval); |
| 1272 #else | 1235 #else |
| 1273 int result = usleep(interval); | 1236 int result = usleep(interval); |
| 1274 #ifdef DEBUG | 1237 #ifdef DEBUG |
| 1275 if (result != 0 && errno != EINTR) { | 1238 if (result != 0 && errno != EINTR) { |
| 1276 fprintf(stderr, | 1239 fprintf(stderr, |
| 1277 "SignalSender usleep error; interval = %u, errno = %d\n", | 1240 "SignalSender usleep error; interval = %u, errno = %d\n", |
| 1278 interval, | 1241 interval, |
| 1279 errno); | 1242 errno); |
| 1280 ASSERT(result == 0 || errno == EINTR); | 1243 ASSERT(result == 0 || errno == EINTR); |
| 1281 } | 1244 } |
| 1282 #endif // DEBUG | 1245 #endif // DEBUG |
| 1283 USE(result); | 1246 USE(result); |
| 1284 #endif // ANDROID | 1247 #endif // ANDROID |
| 1285 } | 1248 } |
| 1286 | 1249 |
| 1250 const int vm_tgid_; |
| 1287 const int interval_; | 1251 const int interval_; |
| 1288 | 1252 |
| 1289 // Protects the process wide state below. | 1253 // Protects the process wide state below. |
| 1290 static Mutex* mutex_; | 1254 static Mutex* mutex_; |
| 1291 static SignalSender* instance_; | 1255 static SignalSender* instance_; |
| 1256 static bool signal_handler_installed_; |
| 1292 static struct sigaction old_signal_handler_; | 1257 static struct sigaction old_signal_handler_; |
| 1293 | 1258 |
| 1294 private: | 1259 private: |
| 1295 DISALLOW_COPY_AND_ASSIGN(SignalSender); | 1260 DISALLOW_COPY_AND_ASSIGN(SignalSender); |
| 1296 }; | 1261 }; |
| 1297 | 1262 |
| 1298 | 1263 |
| 1299 Mutex* SignalSender::mutex_ = NULL; | 1264 Mutex* SignalSender::mutex_ = NULL; |
| 1300 SignalSender* SignalSender::instance_ = NULL; | 1265 SignalSender* SignalSender::instance_ = NULL; |
| 1301 struct sigaction SignalSender::old_signal_handler_; | 1266 struct sigaction SignalSender::old_signal_handler_; |
| 1267 bool SignalSender::signal_handler_installed_ = false; |
| 1302 | 1268 |
| 1303 | 1269 |
| 1304 void OS::SetUp() { | 1270 void OS::SetUp() { |
| 1305 // Seed the random number generator. We preserve microsecond resolution. | 1271 // Seed the random number generator. We preserve microsecond resolution. |
| 1306 uint64_t seed = Ticks() ^ (getpid() << 16); | 1272 uint64_t seed = Ticks() ^ (getpid() << 16); |
| 1307 srandom(static_cast<unsigned int>(seed)); | 1273 srandom(static_cast<unsigned int>(seed)); |
| 1308 limit_mutex = CreateMutex(); | 1274 limit_mutex = CreateMutex(); |
| 1309 | 1275 |
| 1310 #ifdef __arm__ | 1276 #ifdef __arm__ |
| 1311 // When running on ARM hardware check that the EABI used by V8 and | 1277 // When running on ARM hardware check that the EABI used by V8 and |
| 1312 // by the C code is the same. | 1278 // by the C code is the same. |
| 1313 bool hard_float = OS::ArmUsingHardFloat(); | 1279 bool hard_float = OS::ArmUsingHardFloat(); |
| 1314 if (hard_float) { | 1280 if (hard_float) { |
| 1315 #if !USE_EABI_HARDFLOAT | 1281 #if !USE_EABI_HARDFLOAT |
| 1316 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " | 1282 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " |
| 1317 "-DUSE_EABI_HARDFLOAT\n"); | 1283 "-DUSE_EABI_HARDFLOAT\n"); |
| 1318 exit(1); | 1284 exit(1); |
| 1319 #endif | 1285 #endif |
| 1320 } else { | 1286 } else { |
| 1321 #if USE_EABI_HARDFLOAT | 1287 #if USE_EABI_HARDFLOAT |
| 1322 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " | 1288 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " |
| 1323 "-DUSE_EABI_HARDFLOAT\n"); | 1289 "-DUSE_EABI_HARDFLOAT\n"); |
| 1324 exit(1); | 1290 exit(1); |
| 1325 #endif | 1291 #endif |
| 1326 } | 1292 } |
| 1327 #endif | 1293 #endif |
| 1328 SignalSender::SetUp(); | 1294 SignalSender::SetUp(); |
| 1329 CpuProfilerSignalHandler::SetUp(); | |
| 1330 } | 1295 } |
| 1331 | 1296 |
| 1332 | 1297 |
| 1333 void OS::TearDown() { | 1298 void OS::TearDown() { |
| 1334 CpuProfilerSignalHandler::TearDown(); | |
| 1335 SignalSender::TearDown(); | 1299 SignalSender::TearDown(); |
| 1336 delete limit_mutex; | 1300 delete limit_mutex; |
| 1337 } | 1301 } |
| 1338 | 1302 |
| 1339 | 1303 |
| 1340 Sampler::Sampler(Isolate* isolate, int interval) | 1304 Sampler::Sampler(Isolate* isolate, int interval) |
| 1341 : isolate_(isolate), | 1305 : isolate_(isolate), |
| 1342 interval_(interval), | 1306 interval_(interval), |
| 1343 profiling_(false), | 1307 profiling_(false), |
| 1344 has_processing_thread_(false), | |
| 1345 active_(false), | 1308 active_(false), |
| 1346 samples_taken_(0) { | 1309 samples_taken_(0) { |
| 1347 data_ = new PlatformData; | 1310 data_ = new PlatformData; |
| 1348 } | 1311 } |
| 1349 | 1312 |
| 1350 | 1313 |
| 1351 Sampler::~Sampler() { | 1314 Sampler::~Sampler() { |
| 1352 ASSERT(!IsActive()); | 1315 ASSERT(!IsActive()); |
| 1353 delete data_; | 1316 delete data_; |
| 1354 } | 1317 } |
| 1355 | 1318 |
| 1356 | 1319 |
| 1357 void Sampler::Start() { | 1320 void Sampler::Start() { |
| 1358 ASSERT(!IsActive()); | 1321 ASSERT(!IsActive()); |
| 1359 SetActive(true); | 1322 SetActive(true); |
| 1360 SignalSender::AddActiveSampler(this); | 1323 SignalSender::AddActiveSampler(this); |
| 1361 } | 1324 } |
| 1362 | 1325 |
| 1363 | 1326 |
| 1364 void Sampler::Stop() { | 1327 void Sampler::Stop() { |
| 1365 ASSERT(IsActive()); | 1328 ASSERT(IsActive()); |
| 1366 SignalSender::RemoveActiveSampler(this); | 1329 SignalSender::RemoveActiveSampler(this); |
| 1367 SetActive(false); | 1330 SetActive(false); |
| 1368 } | 1331 } |
| 1369 | 1332 |
| 1370 | 1333 |
| 1371 bool Sampler::CanSampleOnProfilerEventsProcessorThread() { | |
| 1372 return true; | |
| 1373 } | |
| 1374 | |
| 1375 | |
| 1376 void Sampler::DoSample() { | |
| 1377 platform_data()->SendProfilingSignal(); | |
| 1378 } | |
| 1379 | |
| 1380 | |
| 1381 void Sampler::StartProfiling() { | |
| 1382 platform_data()->set_signal_handler_installed( | |
| 1383 CpuProfilerSignalHandler::RegisterProfilingSampler()); | |
| 1384 } | |
| 1385 | |
| 1386 | |
| 1387 void Sampler::StopProfiling() { | |
| 1388 CpuProfilerSignalHandler::UnregisterProfilingSampler(); | |
| 1389 platform_data()->set_signal_handler_installed(false); | |
| 1390 } | |
| 1391 | |
| 1392 | |
| 1393 } } // namespace v8::internal | 1334 } } // namespace v8::internal |
| OLD | NEW |