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 |