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 27 matching lines...) Expand all Loading... |
38 #include "macro-assembler.h" | 38 #include "macro-assembler.h" |
39 #include "platform.h" | 39 #include "platform.h" |
40 #include "runtime-profiler.h" | 40 #include "runtime-profiler.h" |
41 #include "serialize.h" | 41 #include "serialize.h" |
42 #include "string-stream.h" | 42 #include "string-stream.h" |
43 #include "vm-state-inl.h" | 43 #include "vm-state-inl.h" |
44 | 44 |
45 namespace v8 { | 45 namespace v8 { |
46 namespace internal { | 46 namespace internal { |
47 | 47 |
| 48 |
| 49 // Low-level logging support. |
| 50 class LowLevelLogger { |
| 51 public: |
| 52 explicit LowLevelLogger(const char* file_name); |
| 53 ~LowLevelLogger(); |
| 54 |
| 55 void CodeCreateEvent(Code* code, const char* name, int name_size); |
| 56 void CodeMoveEvent(Address from, Address to); |
| 57 void CodeDeleteEvent(Address from); |
| 58 void SnapshotPositionEvent(Address addr, int pos); |
| 59 void CodeMovingGCEvent(); |
| 60 |
| 61 private: |
| 62 // Low-level profiling event structures. |
| 63 |
| 64 struct CodeCreateStruct { |
| 65 static const char kTag = 'C'; |
| 66 |
| 67 int32_t name_size; |
| 68 Address code_address; |
| 69 int32_t code_size; |
| 70 }; |
| 71 |
| 72 |
| 73 struct CodeMoveStruct { |
| 74 static const char kTag = 'M'; |
| 75 |
| 76 Address from_address; |
| 77 Address to_address; |
| 78 }; |
| 79 |
| 80 |
| 81 struct CodeDeleteStruct { |
| 82 static const char kTag = 'D'; |
| 83 |
| 84 Address address; |
| 85 }; |
| 86 |
| 87 |
| 88 struct SnapshotPositionStruct { |
| 89 static const char kTag = 'P'; |
| 90 |
| 91 Address address; |
| 92 int32_t position; |
| 93 }; |
| 94 |
| 95 |
| 96 static const char kCodeMovingGCTag = 'G'; |
| 97 |
| 98 |
| 99 // Extension added to V8 log file name to get the low-level log name. |
| 100 static const char kLogExt[]; |
| 101 |
| 102 // File buffer size of the low-level log. We don't use the default to |
| 103 // minimize the associated overhead. |
| 104 static const int kLogBufferSize = 2 * MB; |
| 105 |
| 106 void LogCodeInfo(); |
| 107 void LogWriteBytes(const char* bytes, int size); |
| 108 |
| 109 template <typename T> |
| 110 void LogWriteStruct(const T& s) { |
| 111 char tag = T::kTag; |
| 112 LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag)); |
| 113 LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s)); |
| 114 } |
| 115 |
| 116 FILE* ll_output_handle_; |
| 117 }; |
| 118 |
| 119 const char LowLevelLogger::kLogExt[] = ".ll"; |
| 120 |
| 121 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call; |
| 122 |
| 123 |
48 // The Profiler samples pc and sp values for the main thread. | 124 // The Profiler samples pc and sp values for the main thread. |
49 // Each sample is appended to a circular buffer. | 125 // Each sample is appended to a circular buffer. |
50 // An independent thread removes data and writes it to the log. | 126 // An independent thread removes data and writes it to the log. |
51 // This design minimizes the time spent in the sampler. | 127 // This design minimizes the time spent in the sampler. |
52 // | 128 // |
53 class Profiler: public Thread { | 129 class Profiler: public Thread { |
54 public: | 130 public: |
55 explicit Profiler(Isolate* isolate); | 131 explicit Profiler(Isolate* isolate); |
56 void Engage(); | 132 void Engage(); |
57 void Disengage(); | 133 void Disengage(); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 void Profiler::Run() { | 279 void Profiler::Run() { |
204 TickSample sample; | 280 TickSample sample; |
205 bool overflow = Remove(&sample); | 281 bool overflow = Remove(&sample); |
206 while (running_) { | 282 while (running_) { |
207 LOG(isolate_, TickEvent(&sample, overflow)); | 283 LOG(isolate_, TickEvent(&sample, overflow)); |
208 overflow = Remove(&sample); | 284 overflow = Remove(&sample); |
209 } | 285 } |
210 } | 286 } |
211 | 287 |
212 | 288 |
213 // Low-level profiling event structures. | |
214 | |
215 struct LowLevelCodeCreateStruct { | |
216 static const char kTag = 'C'; | |
217 | |
218 int32_t name_size; | |
219 Address code_address; | |
220 int32_t code_size; | |
221 }; | |
222 | |
223 | |
224 struct LowLevelCodeMoveStruct { | |
225 static const char kTag = 'M'; | |
226 | |
227 Address from_address; | |
228 Address to_address; | |
229 }; | |
230 | |
231 | |
232 struct LowLevelCodeDeleteStruct { | |
233 static const char kTag = 'D'; | |
234 | |
235 Address address; | |
236 }; | |
237 | |
238 | |
239 struct LowLevelSnapshotPositionStruct { | |
240 static const char kTag = 'P'; | |
241 | |
242 Address address; | |
243 int32_t position; | |
244 }; | |
245 | |
246 | |
247 static const char kCodeMovingGCTag = 'G'; | |
248 | |
249 | |
250 // | 289 // |
251 // Logger class implementation. | 290 // Logger class implementation. |
252 // | 291 // |
253 | 292 |
254 class Logger::NameMap { | 293 class Logger::NameMap { |
255 public: | 294 public: |
256 NameMap() : impl_(&PointerEquals) {} | 295 NameMap() : impl_(&PointerEquals) {} |
257 | 296 |
258 ~NameMap() { | 297 ~NameMap() { |
259 for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) { | 298 for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 | 437 |
399 | 438 |
400 Logger::Logger(Isolate* isolate) | 439 Logger::Logger(Isolate* isolate) |
401 : isolate_(isolate), | 440 : isolate_(isolate), |
402 ticker_(NULL), | 441 ticker_(NULL), |
403 profiler_(NULL), | 442 profiler_(NULL), |
404 log_events_(NULL), | 443 log_events_(NULL), |
405 logging_nesting_(0), | 444 logging_nesting_(0), |
406 cpu_profiler_nesting_(0), | 445 cpu_profiler_nesting_(0), |
407 log_(new Log(this)), | 446 log_(new Log(this)), |
| 447 ll_logger_(NULL), |
408 name_buffer_(new NameBuffer), | 448 name_buffer_(new NameBuffer), |
409 address_to_name_map_(NULL), | 449 address_to_name_map_(NULL), |
410 is_initialized_(false), | 450 is_initialized_(false), |
411 code_event_handler_(NULL), | 451 code_event_handler_(NULL), |
412 last_address_(NULL), | 452 last_address_(NULL), |
413 prev_sp_(NULL), | 453 prev_sp_(NULL), |
414 prev_function_(NULL), | 454 prev_function_(NULL), |
415 prev_to_(NULL), | 455 prev_to_(NULL), |
416 prev_code_(NULL), | 456 prev_code_(NULL), |
417 epoch_(0) { | 457 epoch_(0) { |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 void Logger::LogRecordedBuffer(Code* code, SharedFunctionInfo* shared) { | 985 void Logger::LogRecordedBuffer(Code* code, SharedFunctionInfo* shared) { |
946 if (code_event_handler_ != NULL) { | 986 if (code_event_handler_ != NULL) { |
947 Script* script = shared && shared->script()->IsScript() ? | 987 Script* script = shared && shared->script()->IsScript() ? |
948 Script::cast(shared->script()) : NULL; | 988 Script::cast(shared->script()) : NULL; |
949 IssueCodeAddedEvent(code, | 989 IssueCodeAddedEvent(code, |
950 script, | 990 script, |
951 name_buffer_->get(), | 991 name_buffer_->get(), |
952 name_buffer_->size()); | 992 name_buffer_->size()); |
953 } | 993 } |
954 if (!log_->IsEnabled()) return; | 994 if (!log_->IsEnabled()) return; |
955 if (FLAG_ll_prof) { | 995 LL_LOG(CodeCreateEvent(code, name_buffer_->get(), name_buffer_->size())); |
956 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size()); | |
957 } | |
958 if (Serializer::enabled()) { | 996 if (Serializer::enabled()) { |
959 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size()); | 997 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size()); |
960 } | 998 } |
961 } | 999 } |
962 | 1000 |
963 | 1001 |
964 void Logger::AppendCodeCreateHeader(LogMessageBuilder* msg, | 1002 void Logger::AppendCodeCreateHeader(LogMessageBuilder* msg, |
965 LogEventsAndTags tag, | 1003 LogEventsAndTags tag, |
966 Code* code) { | 1004 Code* code) { |
967 ASSERT(msg); | 1005 ASSERT(msg); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 LogMessageBuilder msg(this); | 1173 LogMessageBuilder msg(this); |
1136 AppendCodeCreateHeader(&msg, tag, code); | 1174 AppendCodeCreateHeader(&msg, tag, code); |
1137 msg.Append("\"args_count: %d\"", args_count); | 1175 msg.Append("\"args_count: %d\"", args_count); |
1138 msg.Append('\n'); | 1176 msg.Append('\n'); |
1139 msg.WriteToLogFile(); | 1177 msg.WriteToLogFile(); |
1140 } | 1178 } |
1141 | 1179 |
1142 | 1180 |
1143 void Logger::CodeMovingGCEvent() { | 1181 void Logger::CodeMovingGCEvent() { |
1144 if (!log_->IsEnabled() || !FLAG_ll_prof) return; | 1182 if (!log_->IsEnabled() || !FLAG_ll_prof) return; |
1145 LowLevelLogWriteBytes(&kCodeMovingGCTag, sizeof(kCodeMovingGCTag)); | 1183 LL_LOG(CodeMovingGCEvent()); |
1146 OS::SignalCodeMovingGC(); | 1184 OS::SignalCodeMovingGC(); |
1147 } | 1185 } |
1148 | 1186 |
1149 | 1187 |
1150 void Logger::RegExpCodeCreateEvent(Code* code, String* source) { | 1188 void Logger::RegExpCodeCreateEvent(Code* code, String* source) { |
1151 if (!is_logging_code_events()) return; | 1189 if (!is_logging_code_events()) return; |
1152 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) { | 1190 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) { |
1153 InitNameBuffer(REG_EXP_TAG); | 1191 InitNameBuffer(REG_EXP_TAG); |
1154 name_buffer_->AppendString(source); | 1192 name_buffer_->AppendString(source); |
1155 LogRecordedBuffer(code, NULL); | 1193 LogRecordedBuffer(code, NULL); |
1156 } | 1194 } |
1157 | 1195 |
1158 if (!FLAG_log_code || !log_->IsEnabled()) return; | 1196 if (!FLAG_log_code || !log_->IsEnabled()) return; |
1159 LogMessageBuilder msg(this); | 1197 LogMessageBuilder msg(this); |
1160 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code); | 1198 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code); |
1161 msg.Append('"'); | 1199 msg.Append('"'); |
1162 msg.AppendDetailed(source, false); | 1200 msg.AppendDetailed(source, false); |
1163 msg.Append('"'); | 1201 msg.Append('"'); |
1164 msg.Append('\n'); | 1202 msg.Append('\n'); |
1165 msg.WriteToLogFile(); | 1203 msg.WriteToLogFile(); |
1166 } | 1204 } |
1167 | 1205 |
1168 | 1206 |
1169 void Logger::CodeMoveEvent(Address from, Address to) { | 1207 void Logger::CodeMoveEvent(Address from, Address to) { |
1170 if (code_event_handler_ != NULL) IssueCodeMovedEvent(from, to); | 1208 if (code_event_handler_ != NULL) IssueCodeMovedEvent(from, to); |
1171 if (!log_->IsEnabled()) return; | 1209 if (!log_->IsEnabled()) return; |
1172 if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to); | 1210 LL_LOG(CodeMoveEvent(from, to)); |
1173 if (Serializer::enabled() && address_to_name_map_ != NULL) { | 1211 if (Serializer::enabled() && address_to_name_map_ != NULL) { |
1174 address_to_name_map_->Move(from, to); | 1212 address_to_name_map_->Move(from, to); |
1175 } | 1213 } |
1176 MoveEventInternal(CODE_MOVE_EVENT, from, to); | 1214 MoveEventInternal(CODE_MOVE_EVENT, from, to); |
1177 } | 1215 } |
1178 | 1216 |
1179 | 1217 |
1180 void Logger::CodeDeleteEvent(Address from) { | 1218 void Logger::CodeDeleteEvent(Address from) { |
1181 if (code_event_handler_ != NULL) IssueCodeRemovedEvent(from); | 1219 if (code_event_handler_ != NULL) IssueCodeRemovedEvent(from); |
1182 if (!log_->IsEnabled()) return; | 1220 if (!log_->IsEnabled()) return; |
1183 if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from); | 1221 LL_LOG(CodeDeleteEvent(from)); |
1184 if (Serializer::enabled() && address_to_name_map_ != NULL) { | 1222 if (Serializer::enabled() && address_to_name_map_ != NULL) { |
1185 address_to_name_map_->Remove(from); | 1223 address_to_name_map_->Remove(from); |
1186 } | 1224 } |
1187 DeleteEventInternal(CODE_DELETE_EVENT, from); | 1225 DeleteEventInternal(CODE_DELETE_EVENT, from); |
1188 } | 1226 } |
1189 | 1227 |
1190 void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data, | 1228 void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data, |
1191 int pc_offset, | 1229 int pc_offset, |
1192 int position) { | 1230 int position) { |
1193 if (code_event_handler_ != NULL) { | 1231 if (code_event_handler_ != NULL) { |
(...skipping 25 matching lines...) Expand all Loading... |
1219 void Logger::CodeEndLinePosInfoRecordEvent(Code* code, | 1257 void Logger::CodeEndLinePosInfoRecordEvent(Code* code, |
1220 void* jit_handler_data) { | 1258 void* jit_handler_data) { |
1221 if (code_event_handler_ != NULL) { | 1259 if (code_event_handler_ != NULL) { |
1222 IssueEndCodePosInfoEvent(code, jit_handler_data); | 1260 IssueEndCodePosInfoEvent(code, jit_handler_data); |
1223 } | 1261 } |
1224 } | 1262 } |
1225 | 1263 |
1226 | 1264 |
1227 void Logger::SnapshotPositionEvent(Address addr, int pos) { | 1265 void Logger::SnapshotPositionEvent(Address addr, int pos) { |
1228 if (!log_->IsEnabled()) return; | 1266 if (!log_->IsEnabled()) return; |
1229 if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos); | 1267 LL_LOG(SnapshotPositionEvent(addr, pos)); |
1230 if (Serializer::enabled() && address_to_name_map_ != NULL) { | 1268 if (Serializer::enabled() && address_to_name_map_ != NULL) { |
1231 const char* code_name = address_to_name_map_->Lookup(addr); | 1269 const char* code_name = address_to_name_map_->Lookup(addr); |
1232 if (code_name == NULL) return; // Not a code object. | 1270 if (code_name == NULL) return; // Not a code object. |
1233 LogMessageBuilder msg(this); | 1271 LogMessageBuilder msg(this); |
1234 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos); | 1272 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos); |
1235 msg.AppendDoubleQuotedString(code_name); | 1273 msg.AppendDoubleQuotedString(code_name); |
1236 msg.Append("\n"); | 1274 msg.Append("\n"); |
1237 msg.WriteToLogFile(); | 1275 msg.WriteToLogFile(); |
1238 } | 1276 } |
1239 if (!FLAG_log_snapshot_positions) return; | 1277 if (!FLAG_log_snapshot_positions) return; |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 description = "A keyed call IC from the snapshot"; | 1595 description = "A keyed call IC from the snapshot"; |
1558 tag = Logger::KEYED_CALL_IC_TAG; | 1596 tag = Logger::KEYED_CALL_IC_TAG; |
1559 break; | 1597 break; |
1560 case Code::NUMBER_OF_KINDS: | 1598 case Code::NUMBER_OF_KINDS: |
1561 break; | 1599 break; |
1562 } | 1600 } |
1563 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description)); | 1601 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description)); |
1564 } | 1602 } |
1565 | 1603 |
1566 | 1604 |
1567 void Logger::LogCodeInfo() { | 1605 void Logger::RegisterSnapshotCodeName(Code* code, |
1568 if (!log_->IsEnabled() || !FLAG_ll_prof) return; | 1606 const char* name, |
| 1607 int name_size) { |
| 1608 ASSERT(Serializer::enabled()); |
| 1609 if (address_to_name_map_ == NULL) { |
| 1610 address_to_name_map_ = new NameMap; |
| 1611 } |
| 1612 address_to_name_map_->Insert(code->address(), name, name_size); |
| 1613 } |
| 1614 |
| 1615 |
| 1616 LowLevelLogger::LowLevelLogger(const char* name) |
| 1617 : ll_output_handle_(NULL) { |
| 1618 // Open the low-level log file. |
| 1619 size_t len = strlen(name); |
| 1620 ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt))); |
| 1621 OS::MemCopy(ll_name.start(), name, len); |
| 1622 OS::MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt)); |
| 1623 ll_output_handle_ = OS::FOpen(ll_name.start(), OS::LogFileOpenMode); |
| 1624 setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize); |
| 1625 |
| 1626 LogCodeInfo(); |
| 1627 } |
| 1628 |
| 1629 |
| 1630 LowLevelLogger::~LowLevelLogger() { |
| 1631 fclose(ll_output_handle_); |
| 1632 ll_output_handle_ = NULL; |
| 1633 } |
| 1634 |
| 1635 |
| 1636 void LowLevelLogger::LogCodeInfo() { |
1569 #if V8_TARGET_ARCH_IA32 | 1637 #if V8_TARGET_ARCH_IA32 |
1570 const char arch[] = "ia32"; | 1638 const char arch[] = "ia32"; |
1571 #elif V8_TARGET_ARCH_X64 | 1639 #elif V8_TARGET_ARCH_X64 |
1572 const char arch[] = "x64"; | 1640 const char arch[] = "x64"; |
1573 #elif V8_TARGET_ARCH_ARM | 1641 #elif V8_TARGET_ARCH_ARM |
1574 const char arch[] = "arm"; | 1642 const char arch[] = "arm"; |
1575 #elif V8_TARGET_ARCH_MIPS | 1643 #elif V8_TARGET_ARCH_MIPS |
1576 const char arch[] = "mips"; | 1644 const char arch[] = "mips"; |
1577 #else | 1645 #else |
1578 const char arch[] = "unknown"; | 1646 const char arch[] = "unknown"; |
1579 #endif | 1647 #endif |
1580 LowLevelLogWriteBytes(arch, sizeof(arch)); | 1648 LogWriteBytes(arch, sizeof(arch)); |
1581 } | 1649 } |
1582 | 1650 |
1583 | 1651 void LowLevelLogger::CodeCreateEvent(Code* code, |
1584 void Logger::RegisterSnapshotCodeName(Code* code, | |
1585 const char* name, | |
1586 int name_size) { | |
1587 ASSERT(Serializer::enabled()); | |
1588 if (address_to_name_map_ == NULL) { | |
1589 address_to_name_map_ = new NameMap; | |
1590 } | |
1591 address_to_name_map_->Insert(code->address(), name, name_size); | |
1592 } | |
1593 | |
1594 | |
1595 void Logger::LowLevelCodeCreateEvent(Code* code, | |
1596 const char* name, | 1652 const char* name, |
1597 int name_size) { | 1653 int name_size) { |
1598 if (log_->ll_output_handle_ == NULL) return; | 1654 CodeCreateStruct event; |
1599 LowLevelCodeCreateStruct event; | |
1600 event.name_size = name_size; | 1655 event.name_size = name_size; |
1601 event.code_address = code->instruction_start(); | 1656 event.code_address = code->instruction_start(); |
1602 ASSERT(event.code_address == code->address() + Code::kHeaderSize); | 1657 ASSERT(event.code_address == code->address() + Code::kHeaderSize); |
1603 event.code_size = code->instruction_size(); | 1658 event.code_size = code->instruction_size(); |
1604 LowLevelLogWriteStruct(event); | 1659 LogWriteStruct(event); |
1605 LowLevelLogWriteBytes(name, name_size); | 1660 LogWriteBytes(name, name_size); |
1606 LowLevelLogWriteBytes( | 1661 LogWriteBytes( |
1607 reinterpret_cast<const char*>(code->instruction_start()), | 1662 reinterpret_cast<const char*>(code->instruction_start()), |
1608 code->instruction_size()); | 1663 code->instruction_size()); |
1609 } | 1664 } |
1610 | 1665 |
1611 | 1666 |
1612 void Logger::LowLevelCodeMoveEvent(Address from, Address to) { | 1667 void LowLevelLogger::CodeMoveEvent(Address from, Address to) { |
1613 if (log_->ll_output_handle_ == NULL) return; | 1668 CodeMoveStruct event; |
1614 LowLevelCodeMoveStruct event; | |
1615 event.from_address = from + Code::kHeaderSize; | 1669 event.from_address = from + Code::kHeaderSize; |
1616 event.to_address = to + Code::kHeaderSize; | 1670 event.to_address = to + Code::kHeaderSize; |
1617 LowLevelLogWriteStruct(event); | 1671 LogWriteStruct(event); |
1618 } | 1672 } |
1619 | 1673 |
1620 | 1674 |
1621 void Logger::LowLevelCodeDeleteEvent(Address from) { | 1675 void LowLevelLogger::CodeDeleteEvent(Address from) { |
1622 if (log_->ll_output_handle_ == NULL) return; | 1676 CodeDeleteStruct event; |
1623 LowLevelCodeDeleteStruct event; | |
1624 event.address = from + Code::kHeaderSize; | 1677 event.address = from + Code::kHeaderSize; |
1625 LowLevelLogWriteStruct(event); | 1678 LogWriteStruct(event); |
1626 } | 1679 } |
1627 | 1680 |
1628 | 1681 |
1629 void Logger::LowLevelSnapshotPositionEvent(Address addr, int pos) { | 1682 void LowLevelLogger::SnapshotPositionEvent(Address addr, int pos) { |
1630 if (log_->ll_output_handle_ == NULL) return; | 1683 SnapshotPositionStruct event; |
1631 LowLevelSnapshotPositionStruct event; | |
1632 event.address = addr + Code::kHeaderSize; | 1684 event.address = addr + Code::kHeaderSize; |
1633 event.position = pos; | 1685 event.position = pos; |
1634 LowLevelLogWriteStruct(event); | 1686 LogWriteStruct(event); |
1635 } | 1687 } |
1636 | 1688 |
1637 | 1689 |
1638 void Logger::LowLevelLogWriteBytes(const char* bytes, int size) { | 1690 void LowLevelLogger::LogWriteBytes(const char* bytes, int size) { |
1639 size_t rv = fwrite(bytes, 1, size, log_->ll_output_handle_); | 1691 size_t rv = fwrite(bytes, 1, size, ll_output_handle_); |
1640 ASSERT(static_cast<size_t>(size) == rv); | 1692 ASSERT(static_cast<size_t>(size) == rv); |
1641 USE(rv); | 1693 USE(rv); |
1642 } | 1694 } |
1643 | 1695 |
1644 | 1696 |
| 1697 void LowLevelLogger::CodeMovingGCEvent() { |
| 1698 const char tag = kCodeMovingGCTag; |
| 1699 |
| 1700 LogWriteBytes(&tag, sizeof(tag)); |
| 1701 } |
| 1702 |
| 1703 |
1645 void Logger::LogCodeObjects() { | 1704 void Logger::LogCodeObjects() { |
1646 Heap* heap = isolate_->heap(); | 1705 Heap* heap = isolate_->heap(); |
1647 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 1706 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
1648 "Logger::LogCodeObjects"); | 1707 "Logger::LogCodeObjects"); |
1649 HeapIterator iterator(heap); | 1708 HeapIterator iterator(heap); |
1650 DisallowHeapAllocation no_gc; | 1709 DisallowHeapAllocation no_gc; |
1651 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 1710 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
1652 if (obj->IsCode()) LogCodeObject(obj); | 1711 if (obj->IsCode()) LogCodeObject(obj); |
1653 } | 1712 } |
1654 } | 1713 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1737 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry)); | 1796 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry)); |
1738 } | 1797 } |
1739 Address setter_entry = v8::ToCData<Address>(ai->setter()); | 1798 Address setter_entry = v8::ToCData<Address>(ai->setter()); |
1740 if (setter_entry != 0) { | 1799 if (setter_entry != 0) { |
1741 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry)); | 1800 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry)); |
1742 } | 1801 } |
1743 } | 1802 } |
1744 } | 1803 } |
1745 | 1804 |
1746 | 1805 |
| 1806 static void AddIsolateIdIfNeeded(StringStream* stream) { |
| 1807 Isolate* isolate = Isolate::Current(); |
| 1808 if (isolate->IsDefaultIsolate()) return; |
| 1809 stream->Add("isolate-%p-", isolate); |
| 1810 } |
| 1811 |
| 1812 |
| 1813 static SmartArrayPointer<const char> PrepareLogFileName(const char* file_name) { |
| 1814 if (strchr(file_name, '%') != NULL || |
| 1815 !Isolate::Current()->IsDefaultIsolate()) { |
| 1816 // If there's a '%' in the log file name we have to expand |
| 1817 // placeholders. |
| 1818 HeapStringAllocator allocator; |
| 1819 StringStream stream(&allocator); |
| 1820 AddIsolateIdIfNeeded(&stream); |
| 1821 for (const char* p = file_name; *p; p++) { |
| 1822 if (*p == '%') { |
| 1823 p++; |
| 1824 switch (*p) { |
| 1825 case '\0': |
| 1826 // If there's a % at the end of the string we back up |
| 1827 // one character so we can escape the loop properly. |
| 1828 p--; |
| 1829 break; |
| 1830 case 'p': |
| 1831 stream.Add("%d", OS::GetCurrentProcessId()); |
| 1832 break; |
| 1833 case 't': { |
| 1834 // %t expands to the current time in milliseconds. |
| 1835 double time = OS::TimeCurrentMillis(); |
| 1836 stream.Add("%.0f", FmtElm(time)); |
| 1837 break; |
| 1838 } |
| 1839 case '%': |
| 1840 // %% expands (contracts really) to %. |
| 1841 stream.Put('%'); |
| 1842 break; |
| 1843 default: |
| 1844 // All other %'s expand to themselves. |
| 1845 stream.Put('%'); |
| 1846 stream.Put(*p); |
| 1847 break; |
| 1848 } |
| 1849 } else { |
| 1850 stream.Put(*p); |
| 1851 } |
| 1852 } |
| 1853 return SmartArrayPointer<const char>(stream.ToCString()); |
| 1854 } |
| 1855 int length = StrLength(file_name); |
| 1856 char* str = NewArray<char>(length + 1); |
| 1857 OS::MemCopy(str, file_name, length); |
| 1858 str[length] = '\0'; |
| 1859 return SmartArrayPointer<const char>(str); |
| 1860 } |
| 1861 |
| 1862 |
1747 bool Logger::SetUp(Isolate* isolate) { | 1863 bool Logger::SetUp(Isolate* isolate) { |
1748 // Tests and EnsureInitialize() can call this twice in a row. It's harmless. | 1864 // Tests and EnsureInitialize() can call this twice in a row. It's harmless. |
1749 if (is_initialized_) return true; | 1865 if (is_initialized_) return true; |
1750 is_initialized_ = true; | 1866 is_initialized_ = true; |
1751 | 1867 |
1752 // --ll-prof implies --log-code and --log-snapshot-positions. | 1868 // --ll-prof implies --log-code and --log-snapshot-positions. |
1753 if (FLAG_ll_prof) { | 1869 if (FLAG_ll_prof) { |
1754 FLAG_log_snapshot_positions = true; | 1870 FLAG_log_snapshot_positions = true; |
1755 } | 1871 } |
1756 | 1872 |
1757 // --prof_lazy controls --log-code, implies --noprof_auto. | 1873 // --prof_lazy controls --log-code, implies --noprof_auto. |
1758 if (FLAG_prof_lazy) { | 1874 if (FLAG_prof_lazy) { |
1759 FLAG_log_code = false; | 1875 FLAG_log_code = false; |
1760 FLAG_prof_auto = false; | 1876 FLAG_prof_auto = false; |
1761 } | 1877 } |
1762 | 1878 |
1763 log_->Initialize(); | 1879 SmartArrayPointer<const char> log_file_name = |
| 1880 PrepareLogFileName(FLAG_logfile); |
| 1881 log_->Initialize(*log_file_name); |
1764 | 1882 |
1765 if (FLAG_ll_prof) LogCodeInfo(); | 1883 if (FLAG_ll_prof) { |
| 1884 ll_logger_ = new LowLevelLogger(*log_file_name); |
| 1885 } |
1766 | 1886 |
1767 ticker_ = new Ticker(isolate, kSamplingIntervalMs); | 1887 ticker_ = new Ticker(isolate, kSamplingIntervalMs); |
1768 | 1888 |
1769 if (Log::InitLogAtStart()) { | 1889 if (Log::InitLogAtStart()) { |
1770 logging_nesting_ = 1; | 1890 logging_nesting_ = 1; |
1771 } | 1891 } |
1772 | 1892 |
1773 if (FLAG_prof) { | 1893 if (FLAG_prof) { |
1774 profiler_ = new Profiler(isolate); | 1894 profiler_ = new Profiler(isolate); |
1775 if (!FLAG_prof_auto) { | 1895 if (!FLAG_prof_auto) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 // Stop the profiler before closing the file. | 1932 // Stop the profiler before closing the file. |
1813 if (profiler_ != NULL) { | 1933 if (profiler_ != NULL) { |
1814 profiler_->Disengage(); | 1934 profiler_->Disengage(); |
1815 delete profiler_; | 1935 delete profiler_; |
1816 profiler_ = NULL; | 1936 profiler_ = NULL; |
1817 } | 1937 } |
1818 | 1938 |
1819 delete ticker_; | 1939 delete ticker_; |
1820 ticker_ = NULL; | 1940 ticker_ = NULL; |
1821 | 1941 |
| 1942 if (ll_logger_) { |
| 1943 delete ll_logger_; |
| 1944 ll_logger_ = NULL; |
| 1945 } |
| 1946 |
1822 return log_->Close(); | 1947 return log_->Close(); |
1823 } | 1948 } |
1824 | 1949 |
1825 } } // namespace v8::internal | 1950 } } // namespace v8::internal |
OLD | NEW |