| 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 |