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: | |
yurys
2013/07/15 04:16:35
Consider moving this class and logic related to th
loislo
2013/07/15 07:37:00
I'd like to do that as a separate change.
| |
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(FLAG_logfile, '%') != NULL || | |
yurys
2013/07/15 04:16:35
FLAG_logfile is passed as the parameter and read h
loislo
2013/07/15 07:37:00
FLAG_logfile was replaced with file_name
| |
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 = FLAG_logfile; *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 && Log::InitLogAtStart()) { |
yurys
2013/07/15 04:16:35
Log::InitLogAtStart() check is redundant.
loislo
2013/07/15 07:37:00
Done.
| |
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 |
yurys
2013/07/15 04:16:35
#undefine LL_LOG ?
loislo
2013/07/15 07:37:00
I see no reasons to do that because it gives us no
| |
1825 } } // namespace v8::internal | 1950 } } // namespace v8::internal |
OLD | NEW |