| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 | 115 |
| 116 // Pause and Resume TickSample data collection. | 116 // Pause and Resume TickSample data collection. |
| 117 bool paused() const { return paused_; } | 117 bool paused() const { return paused_; } |
| 118 void pause() { paused_ = true; } | 118 void pause() { paused_ = true; } |
| 119 void resume() { paused_ = false; } | 119 void resume() { paused_ = false; } |
| 120 | 120 |
| 121 private: | 121 private: |
| 122 // Returns the next index in the cyclic buffer. | 122 // Returns the next index in the cyclic buffer. |
| 123 int Succ(int index) { return (index + 1) % kBufferSize; } | 123 int Succ(int index) { return (index + 1) % kBufferSize; } |
| 124 | 124 |
| 125 Isolate* isolate_; |
| 125 // Cyclic buffer for communicating profiling samples | 126 // Cyclic buffer for communicating profiling samples |
| 126 // between the signal handler and the worker thread. | 127 // between the signal handler and the worker thread. |
| 127 static const int kBufferSize = 128; | 128 static const int kBufferSize = 128; |
| 128 TickSample buffer_[kBufferSize]; // Buffer storage. | 129 TickSample buffer_[kBufferSize]; // Buffer storage. |
| 129 int head_; // Index to the buffer head. | 130 int head_; // Index to the buffer head. |
| 130 int tail_; // Index to the buffer tail. | 131 int tail_; // Index to the buffer tail. |
| 131 bool overflow_; // Tell whether a buffer overflow has occurred. | 132 bool overflow_; // Tell whether a buffer overflow has occurred. |
| 132 Semaphore* buffer_semaphore_; // Sempahore used for buffer synchronization. | 133 Semaphore* buffer_semaphore_; // Sempahore used for buffer synchronization. |
| 133 | 134 |
| 134 // Tells whether profiler is engaged, that is, processing thread is stated. | 135 // Tells whether profiler is engaged, that is, processing thread is stated. |
| 135 bool engaged_; | 136 bool engaged_; |
| 136 | 137 |
| 137 // Tells whether worker thread should continue running. | 138 // Tells whether worker thread should continue running. |
| 138 bool running_; | 139 bool running_; |
| 139 | 140 |
| 140 // Tells whether we are currently recording tick samples. | 141 // Tells whether we are currently recording tick samples. |
| 141 bool paused_; | 142 bool paused_; |
| 142 }; | 143 }; |
| 143 | 144 |
| 144 | 145 |
| 145 // | 146 // |
| 146 // StackTracer implementation | 147 // StackTracer implementation |
| 147 // | 148 // |
| 148 void StackTracer::Trace(Isolate* isolate, TickSample* sample) { | 149 void StackTracer::Trace(Isolate* isolate, TickSample* sample) { |
| 149 ASSERT(isolate->IsInitialized()); | 150 ASSERT(isolate->IsInitialized()); |
| 150 | 151 |
| 151 sample->tos = NULL; | |
| 152 sample->frames_count = 0; | |
| 153 sample->has_external_callback = false; | |
| 154 | |
| 155 // Avoid collecting traces while doing GC. | 152 // Avoid collecting traces while doing GC. |
| 156 if (sample->state == GC) return; | 153 if (sample->state == GC) return; |
| 157 | 154 |
| 158 const Address js_entry_sp = | 155 const Address js_entry_sp = |
| 159 Isolate::js_entry_sp(isolate->thread_local_top()); | 156 Isolate::js_entry_sp(isolate->thread_local_top()); |
| 160 if (js_entry_sp == 0) { | 157 if (js_entry_sp == 0) { |
| 161 // Not executing JS now. | 158 // Not executing JS now. |
| 162 return; | 159 return; |
| 163 } | 160 } |
| 164 | 161 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 IncrementStateCounter(state); | 261 IncrementStateCounter(state); |
| 265 ASSERT(IsPowerOf2(kBufferSize)); | 262 ASSERT(IsPowerOf2(kBufferSize)); |
| 266 current_index_ = (current_index_ + 1) & (kBufferSize - 1); | 263 current_index_ = (current_index_ + 1) & (kBufferSize - 1); |
| 267 } | 264 } |
| 268 | 265 |
| 269 | 266 |
| 270 // | 267 // |
| 271 // Profiler implementation. | 268 // Profiler implementation. |
| 272 // | 269 // |
| 273 Profiler::Profiler(Isolate* isolate) | 270 Profiler::Profiler(Isolate* isolate) |
| 274 : Thread(isolate, "v8:Profiler"), | 271 : Thread("v8:Profiler"), |
| 272 isolate_(isolate), |
| 275 head_(0), | 273 head_(0), |
| 276 tail_(0), | 274 tail_(0), |
| 277 overflow_(false), | 275 overflow_(false), |
| 278 buffer_semaphore_(OS::CreateSemaphore(0)), | 276 buffer_semaphore_(OS::CreateSemaphore(0)), |
| 279 engaged_(false), | 277 engaged_(false), |
| 280 running_(false), | 278 running_(false), |
| 281 paused_(false) { | 279 paused_(false) { |
| 282 } | 280 } |
| 283 | 281 |
| 284 | 282 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 Insert(&sample); | 317 Insert(&sample); |
| 320 Join(); | 318 Join(); |
| 321 | 319 |
| 322 LOG(ISOLATE, UncheckedStringEvent("profiler", "end")); | 320 LOG(ISOLATE, UncheckedStringEvent("profiler", "end")); |
| 323 } | 321 } |
| 324 | 322 |
| 325 | 323 |
| 326 void Profiler::Run() { | 324 void Profiler::Run() { |
| 327 TickSample sample; | 325 TickSample sample; |
| 328 bool overflow = Remove(&sample); | 326 bool overflow = Remove(&sample); |
| 329 i::Isolate* isolate = ISOLATE; | |
| 330 while (running_) { | 327 while (running_) { |
| 331 LOG(isolate, TickEvent(&sample, overflow)); | 328 LOG(isolate_, TickEvent(&sample, overflow)); |
| 332 overflow = Remove(&sample); | 329 overflow = Remove(&sample); |
| 333 } | 330 } |
| 334 } | 331 } |
| 335 | 332 |
| 336 | 333 |
| 337 // Low-level profiling event structures. | 334 // Low-level profiling event structures. |
| 338 | 335 |
| 339 struct LowLevelCodeCreateStruct { | 336 struct LowLevelCodeCreateStruct { |
| 340 static const char kTag = 'C'; | 337 static const char kTag = 'C'; |
| 341 | 338 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 } | 389 } |
| 393 } | 390 } |
| 394 | 391 |
| 395 const char* Lookup(Address code_address) { | 392 const char* Lookup(Address code_address) { |
| 396 HashMap::Entry* entry = FindEntry(code_address); | 393 HashMap::Entry* entry = FindEntry(code_address); |
| 397 return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL; | 394 return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL; |
| 398 } | 395 } |
| 399 | 396 |
| 400 void Remove(Address code_address) { | 397 void Remove(Address code_address) { |
| 401 HashMap::Entry* entry = FindEntry(code_address); | 398 HashMap::Entry* entry = FindEntry(code_address); |
| 402 if (entry != NULL) DeleteArray(static_cast<const char*>(entry->value)); | 399 if (entry != NULL) { |
| 403 RemoveEntry(entry); | 400 DeleteArray(static_cast<char*>(entry->value)); |
| 401 RemoveEntry(entry); |
| 402 } |
| 404 } | 403 } |
| 405 | 404 |
| 406 void Move(Address from, Address to) { | 405 void Move(Address from, Address to) { |
| 407 if (from == to) return; | 406 if (from == to) return; |
| 408 HashMap::Entry* from_entry = FindEntry(from); | 407 HashMap::Entry* from_entry = FindEntry(from); |
| 409 ASSERT(from_entry != NULL); | 408 ASSERT(from_entry != NULL); |
| 410 void* value = from_entry->value; | 409 void* value = from_entry->value; |
| 411 RemoveEntry(from_entry); | 410 RemoveEntry(from_entry); |
| 412 HashMap::Entry* to_entry = FindOrCreateEntry(to); | 411 HashMap::Entry* to_entry = FindOrCreateEntry(to); |
| 413 ASSERT(to_entry->value == NULL); | 412 ASSERT(to_entry->value == NULL); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 }; | 514 }; |
| 516 | 515 |
| 517 | 516 |
| 518 Logger::Logger() | 517 Logger::Logger() |
| 519 : ticker_(NULL), | 518 : ticker_(NULL), |
| 520 profiler_(NULL), | 519 profiler_(NULL), |
| 521 sliding_state_window_(NULL), | 520 sliding_state_window_(NULL), |
| 522 log_events_(NULL), | 521 log_events_(NULL), |
| 523 logging_nesting_(0), | 522 logging_nesting_(0), |
| 524 cpu_profiler_nesting_(0), | 523 cpu_profiler_nesting_(0), |
| 525 heap_profiler_nesting_(0), | |
| 526 log_(new Log(this)), | 524 log_(new Log(this)), |
| 527 name_buffer_(new NameBuffer), | 525 name_buffer_(new NameBuffer), |
| 528 address_to_name_map_(NULL), | 526 address_to_name_map_(NULL), |
| 529 is_initialized_(false), | 527 is_initialized_(false), |
| 530 last_address_(NULL), | 528 last_address_(NULL), |
| 531 prev_sp_(NULL), | 529 prev_sp_(NULL), |
| 532 prev_function_(NULL), | 530 prev_function_(NULL), |
| 533 prev_to_(NULL), | 531 prev_to_(NULL), |
| 534 prev_code_(NULL) { | 532 prev_code_(NULL) { |
| 535 } | 533 } |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1280 LogMessageBuilder msg(this); | 1278 LogMessageBuilder msg(this); |
| 1281 // Using non-relative system time in order to be able to synchronize with | 1279 // Using non-relative system time in order to be able to synchronize with |
| 1282 // external memory profiling events (e.g. DOM memory size). | 1280 // external memory profiling events (e.g. DOM memory size). |
| 1283 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n", | 1281 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n", |
| 1284 space, kind, OS::TimeCurrentMillis()); | 1282 space, kind, OS::TimeCurrentMillis()); |
| 1285 msg.WriteToLogFile(); | 1283 msg.WriteToLogFile(); |
| 1286 #endif | 1284 #endif |
| 1287 } | 1285 } |
| 1288 | 1286 |
| 1289 | 1287 |
| 1290 void Logger::HeapSampleStats(const char* space, const char* kind, | |
| 1291 intptr_t capacity, intptr_t used) { | |
| 1292 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 1293 if (!log_->IsEnabled() || !FLAG_log_gc) return; | |
| 1294 LogMessageBuilder msg(this); | |
| 1295 msg.Append("heap-sample-stats,\"%s\",\"%s\"," | |
| 1296 "%" V8_PTR_PREFIX "d,%" V8_PTR_PREFIX "d\n", | |
| 1297 space, kind, capacity, used); | |
| 1298 msg.WriteToLogFile(); | |
| 1299 #endif | |
| 1300 } | |
| 1301 | |
| 1302 | |
| 1303 void Logger::HeapSampleEndEvent(const char* space, const char* kind) { | 1288 void Logger::HeapSampleEndEvent(const char* space, const char* kind) { |
| 1304 #ifdef ENABLE_LOGGING_AND_PROFILING | 1289 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1305 if (!log_->IsEnabled() || !FLAG_log_gc) return; | 1290 if (!log_->IsEnabled() || !FLAG_log_gc) return; |
| 1306 LogMessageBuilder msg(this); | 1291 LogMessageBuilder msg(this); |
| 1307 msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind); | 1292 msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind); |
| 1308 msg.WriteToLogFile(); | 1293 msg.WriteToLogFile(); |
| 1309 #endif | 1294 #endif |
| 1310 } | 1295 } |
| 1311 | 1296 |
| 1312 | 1297 |
| 1313 void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) { | 1298 void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) { |
| 1314 #ifdef ENABLE_LOGGING_AND_PROFILING | 1299 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1315 if (!log_->IsEnabled() || !FLAG_log_gc) return; | 1300 if (!log_->IsEnabled() || !FLAG_log_gc) return; |
| 1316 LogMessageBuilder msg(this); | 1301 LogMessageBuilder msg(this); |
| 1317 msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes); | 1302 msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes); |
| 1318 msg.WriteToLogFile(); | 1303 msg.WriteToLogFile(); |
| 1319 #endif | 1304 #endif |
| 1320 } | 1305 } |
| 1321 | 1306 |
| 1322 | 1307 |
| 1323 void Logger::HeapSampleJSConstructorEvent(const char* constructor, | |
| 1324 int number, int bytes) { | |
| 1325 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 1326 if (!log_->IsEnabled() || !FLAG_log_gc) return; | |
| 1327 LogMessageBuilder msg(this); | |
| 1328 msg.Append("heap-js-cons-item,%s,%d,%d\n", constructor, number, bytes); | |
| 1329 msg.WriteToLogFile(); | |
| 1330 #endif | |
| 1331 } | |
| 1332 | |
| 1333 // Event starts with comma, so we don't have it in the format string. | |
| 1334 static const char kEventText[] = "heap-js-ret-item,%s"; | |
| 1335 // We take placeholder strings into account, but it's OK to be conservative. | |
| 1336 static const int kEventTextLen = sizeof(kEventText)/sizeof(kEventText[0]); | |
| 1337 | |
| 1338 void Logger::HeapSampleJSRetainersEvent( | |
| 1339 const char* constructor, const char* event) { | |
| 1340 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 1341 if (!log_->IsEnabled() || !FLAG_log_gc) return; | |
| 1342 const int cons_len = StrLength(constructor); | |
| 1343 const int event_len = StrLength(event); | |
| 1344 int pos = 0; | |
| 1345 // Retainer lists can be long. We may need to split them into multiple events. | |
| 1346 do { | |
| 1347 LogMessageBuilder msg(this); | |
| 1348 msg.Append(kEventText, constructor); | |
| 1349 int to_write = event_len - pos; | |
| 1350 if (to_write > Log::kMessageBufferSize - (cons_len + kEventTextLen)) { | |
| 1351 int cut_pos = pos + Log::kMessageBufferSize - (cons_len + kEventTextLen); | |
| 1352 ASSERT(cut_pos < event_len); | |
| 1353 while (cut_pos > pos && event[cut_pos] != ',') --cut_pos; | |
| 1354 if (event[cut_pos] != ',') { | |
| 1355 // Crash in debug mode, skip in release mode. | |
| 1356 ASSERT(false); | |
| 1357 return; | |
| 1358 } | |
| 1359 // Append a piece of event that fits, without trailing comma. | |
| 1360 msg.AppendStringPart(event + pos, cut_pos - pos); | |
| 1361 // Start next piece with comma. | |
| 1362 pos = cut_pos; | |
| 1363 } else { | |
| 1364 msg.Append("%s", event + pos); | |
| 1365 pos += event_len; | |
| 1366 } | |
| 1367 msg.Append('\n'); | |
| 1368 msg.WriteToLogFile(); | |
| 1369 } while (pos < event_len); | |
| 1370 #endif | |
| 1371 } | |
| 1372 | |
| 1373 | |
| 1374 void Logger::HeapSampleJSProducerEvent(const char* constructor, | |
| 1375 Address* stack) { | |
| 1376 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 1377 if (!log_->IsEnabled() || !FLAG_log_gc) return; | |
| 1378 LogMessageBuilder msg(this); | |
| 1379 msg.Append("heap-js-prod-item,%s", constructor); | |
| 1380 while (*stack != NULL) { | |
| 1381 msg.Append(",0x%" V8PRIxPTR, *stack++); | |
| 1382 } | |
| 1383 msg.Append("\n"); | |
| 1384 msg.WriteToLogFile(); | |
| 1385 #endif | |
| 1386 } | |
| 1387 | |
| 1388 | |
| 1389 void Logger::DebugTag(const char* call_site_tag) { | 1308 void Logger::DebugTag(const char* call_site_tag) { |
| 1390 #ifdef ENABLE_LOGGING_AND_PROFILING | 1309 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1391 if (!log_->IsEnabled() || !FLAG_log) return; | 1310 if (!log_->IsEnabled() || !FLAG_log) return; |
| 1392 LogMessageBuilder msg(this); | 1311 LogMessageBuilder msg(this); |
| 1393 msg.Append("debug-tag,%s\n", call_site_tag); | 1312 msg.Append("debug-tag,%s\n", call_site_tag); |
| 1394 msg.WriteToLogFile(); | 1313 msg.WriteToLogFile(); |
| 1395 #endif | 1314 #endif |
| 1396 } | 1315 } |
| 1397 | 1316 |
| 1398 | 1317 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1436 } | 1355 } |
| 1437 for (int i = 0; i < sample->frames_count; ++i) { | 1356 for (int i = 0; i < sample->frames_count; ++i) { |
| 1438 msg.Append(','); | 1357 msg.Append(','); |
| 1439 msg.AppendAddress(sample->stack[i]); | 1358 msg.AppendAddress(sample->stack[i]); |
| 1440 } | 1359 } |
| 1441 msg.Append('\n'); | 1360 msg.Append('\n'); |
| 1442 msg.WriteToLogFile(); | 1361 msg.WriteToLogFile(); |
| 1443 } | 1362 } |
| 1444 | 1363 |
| 1445 | 1364 |
| 1446 int Logger::GetActiveProfilerModules() { | 1365 bool Logger::IsProfilerPaused() { |
| 1447 int result = PROFILER_MODULE_NONE; | 1366 return profiler_ == NULL || profiler_->paused(); |
| 1448 if (profiler_ != NULL && !profiler_->paused()) { | |
| 1449 result |= PROFILER_MODULE_CPU; | |
| 1450 } | |
| 1451 if (FLAG_log_gc) { | |
| 1452 result |= PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS; | |
| 1453 } | |
| 1454 return result; | |
| 1455 } | 1367 } |
| 1456 | 1368 |
| 1457 | 1369 |
| 1458 void Logger::PauseProfiler(int flags, int tag) { | 1370 void Logger::PauseProfiler() { |
| 1459 if (!log_->IsEnabled()) return; | 1371 if (!log_->IsEnabled()) return; |
| 1460 if (profiler_ != NULL && (flags & PROFILER_MODULE_CPU)) { | 1372 if (profiler_ != NULL) { |
| 1461 // It is OK to have negative nesting. | 1373 // It is OK to have negative nesting. |
| 1462 if (--cpu_profiler_nesting_ == 0) { | 1374 if (--cpu_profiler_nesting_ == 0) { |
| 1463 profiler_->pause(); | 1375 profiler_->pause(); |
| 1464 if (FLAG_prof_lazy) { | 1376 if (FLAG_prof_lazy) { |
| 1465 if (!FLAG_sliding_state_window && !RuntimeProfiler::IsEnabled()) { | 1377 if (!FLAG_sliding_state_window && !RuntimeProfiler::IsEnabled()) { |
| 1466 ticker_->Stop(); | 1378 ticker_->Stop(); |
| 1467 } | 1379 } |
| 1468 FLAG_log_code = false; | 1380 FLAG_log_code = false; |
| 1469 // Must be the same message as Log::kDynamicBufferSeal. | 1381 // Must be the same message as Log::kDynamicBufferSeal. |
| 1470 LOG(ISOLATE, UncheckedStringEvent("profiler", "pause")); | 1382 LOG(ISOLATE, UncheckedStringEvent("profiler", "pause")); |
| 1471 } | 1383 } |
| 1472 --logging_nesting_; | 1384 --logging_nesting_; |
| 1473 } | 1385 } |
| 1474 } | 1386 } |
| 1475 if (flags & | |
| 1476 (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { | |
| 1477 if (--heap_profiler_nesting_ == 0) { | |
| 1478 FLAG_log_gc = false; | |
| 1479 --logging_nesting_; | |
| 1480 } | |
| 1481 } | |
| 1482 if (tag != 0) { | |
| 1483 UncheckedIntEvent("close-tag", tag); | |
| 1484 } | |
| 1485 } | 1387 } |
| 1486 | 1388 |
| 1487 | 1389 |
| 1488 void Logger::ResumeProfiler(int flags, int tag) { | 1390 void Logger::ResumeProfiler() { |
| 1489 if (!log_->IsEnabled()) return; | 1391 if (!log_->IsEnabled()) return; |
| 1490 if (tag != 0) { | 1392 if (profiler_ != NULL) { |
| 1491 UncheckedIntEvent("open-tag", tag); | |
| 1492 } | |
| 1493 if (profiler_ != NULL && (flags & PROFILER_MODULE_CPU)) { | |
| 1494 if (cpu_profiler_nesting_++ == 0) { | 1393 if (cpu_profiler_nesting_++ == 0) { |
| 1495 ++logging_nesting_; | 1394 ++logging_nesting_; |
| 1496 if (FLAG_prof_lazy) { | 1395 if (FLAG_prof_lazy) { |
| 1497 profiler_->Engage(); | 1396 profiler_->Engage(); |
| 1498 LOG(ISOLATE, UncheckedStringEvent("profiler", "resume")); | 1397 LOG(ISOLATE, UncheckedStringEvent("profiler", "resume")); |
| 1499 FLAG_log_code = true; | 1398 FLAG_log_code = true; |
| 1500 LogCompiledFunctions(); | 1399 LogCompiledFunctions(); |
| 1501 LogAccessorCallbacks(); | 1400 LogAccessorCallbacks(); |
| 1502 if (!FLAG_sliding_state_window && !ticker_->IsActive()) { | 1401 if (!FLAG_sliding_state_window && !ticker_->IsActive()) { |
| 1503 ticker_->Start(); | 1402 ticker_->Start(); |
| 1504 } | 1403 } |
| 1505 } | 1404 } |
| 1506 profiler_->resume(); | 1405 profiler_->resume(); |
| 1507 } | 1406 } |
| 1508 } | 1407 } |
| 1509 if (flags & | |
| 1510 (PROFILER_MODULE_HEAP_STATS | PROFILER_MODULE_JS_CONSTRUCTORS)) { | |
| 1511 if (heap_profiler_nesting_++ == 0) { | |
| 1512 ++logging_nesting_; | |
| 1513 FLAG_log_gc = true; | |
| 1514 } | |
| 1515 } | |
| 1516 } | 1408 } |
| 1517 | 1409 |
| 1518 | 1410 |
| 1519 // This function can be called when Log's mutex is acquired, | 1411 // This function can be called when Log's mutex is acquired, |
| 1520 // either from main or Profiler's thread. | 1412 // either from main or Profiler's thread. |
| 1521 void Logger::LogFailure() { | 1413 void Logger::LogFailure() { |
| 1522 PauseProfiler(PROFILER_MODULE_CPU, 0); | 1414 PauseProfiler(); |
| 1523 } | 1415 } |
| 1524 | 1416 |
| 1525 | 1417 |
| 1526 bool Logger::IsProfilerSamplerActive() { | 1418 bool Logger::IsProfilerSamplerActive() { |
| 1527 return ticker_->IsActive(); | 1419 return ticker_->IsActive(); |
| 1528 } | 1420 } |
| 1529 | 1421 |
| 1530 | 1422 |
| 1531 int Logger::GetLogLines(int from_pos, char* dest_buf, int max_size) { | 1423 int Logger::GetLogLines(int from_pos, char* dest_buf, int max_size) { |
| 1532 return log_->GetLogLines(from_pos, dest_buf, max_size); | 1424 return log_->GetLogLines(from_pos, dest_buf, max_size); |
| 1533 } | 1425 } |
| 1534 | 1426 |
| 1535 | 1427 |
| 1536 class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor { | 1428 class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor { |
| 1537 public: | 1429 public: |
| 1538 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis, | 1430 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis, |
| 1539 Handle<Code>* code_objects, | 1431 Handle<Code>* code_objects, |
| 1540 int* count) | 1432 int* count) |
| 1541 : sfis_(sfis), code_objects_(code_objects), count_(count) { } | 1433 : sfis_(sfis), code_objects_(code_objects), count_(count) { } |
| 1542 | 1434 |
| 1543 virtual void EnterContext(Context* context) {} | 1435 virtual void EnterContext(Context* context) {} |
| 1544 virtual void LeaveContext(Context* context) {} | 1436 virtual void LeaveContext(Context* context) {} |
| 1545 | 1437 |
| 1546 virtual void VisitFunction(JSFunction* function) { | 1438 virtual void VisitFunction(JSFunction* function) { |
| 1439 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared()); |
| 1440 Object* maybe_script = sfi->script(); |
| 1441 if (maybe_script->IsScript() |
| 1442 && !Script::cast(maybe_script)->HasValidSource()) return; |
| 1547 if (sfis_ != NULL) { | 1443 if (sfis_ != NULL) { |
| 1548 sfis_[*count_] = Handle<SharedFunctionInfo>(function->shared()); | 1444 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi); |
| 1549 } | 1445 } |
| 1550 if (code_objects_ != NULL) { | 1446 if (code_objects_ != NULL) { |
| 1551 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); | 1447 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); |
| 1552 code_objects_[*count_] = Handle<Code>(function->code()); | 1448 code_objects_[*count_] = Handle<Code>(function->code()); |
| 1553 } | 1449 } |
| 1554 *count_ = *count_ + 1; | 1450 *count_ = *count_ + 1; |
| 1555 } | 1451 } |
| 1556 | 1452 |
| 1557 private: | 1453 private: |
| 1558 Handle<SharedFunctionInfo>* sfis_; | 1454 Handle<SharedFunctionInfo>* sfis_; |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 } | 1730 } |
| 1835 | 1731 |
| 1836 // TODO(isolates): this assert introduces cyclic dependency (logger | 1732 // TODO(isolates): this assert introduces cyclic dependency (logger |
| 1837 // -> thread local top -> heap -> logger). | 1733 // -> thread local top -> heap -> logger). |
| 1838 // ASSERT(VMState::is_outermost_external()); | 1734 // ASSERT(VMState::is_outermost_external()); |
| 1839 | 1735 |
| 1840 log_->Initialize(); | 1736 log_->Initialize(); |
| 1841 | 1737 |
| 1842 if (FLAG_ll_prof) LogCodeInfo(); | 1738 if (FLAG_ll_prof) LogCodeInfo(); |
| 1843 | 1739 |
| 1844 ticker_ = new Ticker(Isolate::Current(), kSamplingIntervalMs); | 1740 Isolate* isolate = Isolate::Current(); |
| 1741 ticker_ = new Ticker(isolate, kSamplingIntervalMs); |
| 1845 | 1742 |
| 1846 Isolate* isolate = Isolate::Current(); | |
| 1847 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) { | 1743 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) { |
| 1848 sliding_state_window_ = new SlidingStateWindow(isolate); | 1744 sliding_state_window_ = new SlidingStateWindow(isolate); |
| 1849 } | 1745 } |
| 1850 | 1746 |
| 1851 bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api | 1747 bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api |
| 1852 || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect | 1748 || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect |
| 1853 || FLAG_log_regexp || FLAG_log_state_changes || FLAG_ll_prof; | 1749 || FLAG_log_regexp || FLAG_log_state_changes || FLAG_ll_prof; |
| 1854 | 1750 |
| 1855 if (start_logging) { | 1751 if (start_logging) { |
| 1856 logging_nesting_ = 1; | 1752 logging_nesting_ = 1; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1870 | 1766 |
| 1871 return true; | 1767 return true; |
| 1872 | 1768 |
| 1873 #else | 1769 #else |
| 1874 return false; | 1770 return false; |
| 1875 #endif | 1771 #endif |
| 1876 } | 1772 } |
| 1877 | 1773 |
| 1878 | 1774 |
| 1879 Sampler* Logger::sampler() { | 1775 Sampler* Logger::sampler() { |
| 1776 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1880 return ticker_; | 1777 return ticker_; |
| 1778 #else |
| 1779 return NULL; |
| 1780 #endif |
| 1881 } | 1781 } |
| 1882 | 1782 |
| 1883 | 1783 |
| 1884 void Logger::EnsureTickerStarted() { | 1784 void Logger::EnsureTickerStarted() { |
| 1885 #ifdef ENABLE_LOGGING_AND_PROFILING | 1785 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1886 ASSERT(ticker_ != NULL); | 1786 ASSERT(ticker_ != NULL); |
| 1887 if (!ticker_->IsActive()) ticker_->Start(); | 1787 if (!ticker_->IsActive()) ticker_->Start(); |
| 1888 #endif | 1788 #endif |
| 1889 } | 1789 } |
| 1890 | 1790 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1947 for (int i = 0; | 1847 for (int i = 0; |
| 1948 ActiveSamplersExist() && i < active_samplers_->length(); | 1848 ActiveSamplersExist() && i < active_samplers_->length(); |
| 1949 ++i) { | 1849 ++i) { |
| 1950 func(active_samplers_->at(i), param); | 1850 func(active_samplers_->at(i), param); |
| 1951 } | 1851 } |
| 1952 return ActiveSamplersExist(); | 1852 return ActiveSamplersExist(); |
| 1953 } | 1853 } |
| 1954 | 1854 |
| 1955 | 1855 |
| 1956 static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) { | 1856 static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) { |
| 1857 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 1957 bool* flag = reinterpret_cast<bool*>(flag_ptr); | 1858 bool* flag = reinterpret_cast<bool*>(flag_ptr); |
| 1958 *flag |= sampler->IsProfiling(); | 1859 *flag |= sampler->IsProfiling(); |
| 1860 #endif |
| 1959 } | 1861 } |
| 1960 | 1862 |
| 1961 | 1863 |
| 1962 SamplerRegistry::State SamplerRegistry::GetState() { | 1864 SamplerRegistry::State SamplerRegistry::GetState() { |
| 1963 bool flag = false; | 1865 bool flag = false; |
| 1964 if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) { | 1866 if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) { |
| 1965 return HAS_NO_SAMPLERS; | 1867 return HAS_NO_SAMPLERS; |
| 1966 } | 1868 } |
| 1967 return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS; | 1869 return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS; |
| 1968 } | 1870 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1983 void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) { | 1885 void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) { |
| 1984 ASSERT(sampler->IsActive()); | 1886 ASSERT(sampler->IsActive()); |
| 1985 ScopedLock lock(mutex_); | 1887 ScopedLock lock(mutex_); |
| 1986 ASSERT(active_samplers_ != NULL); | 1888 ASSERT(active_samplers_ != NULL); |
| 1987 bool removed = active_samplers_->RemoveElement(sampler); | 1889 bool removed = active_samplers_->RemoveElement(sampler); |
| 1988 ASSERT(removed); | 1890 ASSERT(removed); |
| 1989 USE(removed); | 1891 USE(removed); |
| 1990 } | 1892 } |
| 1991 | 1893 |
| 1992 } } // namespace v8::internal | 1894 } } // namespace v8::internal |
| OLD | NEW |