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