33 |
33 |
34 // Events and EventMark provide interfaces to log events taking place in the vm. |
34 // Events and EventMark provide interfaces to log events taking place in the vm. |
35 // This facility is extremly useful for post-mortem debugging. The eventlog |
35 // This facility is extremly useful for post-mortem debugging. The eventlog |
36 // often provides crucial information about events leading up to the crash. |
36 // often provides crucial information about events leading up to the crash. |
37 // |
37 // |
38 // All arguments past the format string must be passed as an intptr_t. |
38 // Abstractly the logs can record whatever they way but normally they |
39 // |
39 // would record at least a timestamp and the current Thread, along |
40 // To log a single event use: |
40 // with whatever data they need in a ring buffer. Commonly fixed |
41 // Events::log("New nmethod has been created " INTPTR_FORMAT, nm); |
41 // length text messages are recorded for simplicity but other |
42 // |
42 // strategies could be used. Several logs are provided by default but |
43 // To log a block of events use: |
43 // new instances can be created as needed. |
44 // EventMark m("GarbageCollecting %d", (intptr_t)gc_number); |
|
45 // |
|
46 // The constructor to eventlog indents the eventlog until the |
|
47 // destructor has been executed. |
|
48 // |
|
49 // IMPLEMENTATION RESTRICTION: |
|
50 // Max 3 arguments are saved for each logged event. |
|
51 // |
|
52 |
44 |
53 // The base event log dumping class that is registered for dumping at |
45 // The base event log dumping class that is registered for dumping at |
54 // crash time. This is a very generic interface that is mainly here |
46 // crash time. This is a very generic interface that is mainly here |
55 // for completeness. Normally the templated EventLogBase would be |
47 // for completeness. Normally the templated EventLogBase would be |
56 // subclassed to provide different log types. |
48 // subclassed to provide different log types. |
98 _length(length), |
90 _length(length), |
99 _count(0), |
91 _count(0), |
100 _index(0), |
92 _index(0), |
101 _mutex(Mutex::event, name) { |
93 _mutex(Mutex::event, name) { |
102 _records = new EventRecord<T>[length]; |
94 _records = new EventRecord<T>[length]; |
|
95 } |
|
96 |
|
97 double fetch_timestamp() { |
|
98 return tty->time_stamp().seconds(); |
103 } |
99 } |
104 |
100 |
105 // move the ring buffer to next open slot and return the index of |
101 // move the ring buffer to next open slot and return the index of |
106 // the slot to use for the current message. Should only be called |
102 // the slot to use for the current message. Should only be called |
107 // while mutex is held. |
103 // while mutex is held. |
128 // Print a single element. A templated implementation might need to |
124 // Print a single element. A templated implementation might need to |
129 // be declared by subclasses. |
125 // be declared by subclasses. |
130 void print(outputStream* out, T& e); |
126 void print(outputStream* out, T& e); |
131 |
127 |
132 void print(outputStream* out, EventRecord<T>& e) { |
128 void print(outputStream* out, EventRecord<T>& e) { |
133 out->print("Event: " INT64_FORMAT " ", e.timestamp); |
129 out->print("Event: %.3f ", e.timestamp); |
134 if (e.thread != NULL) { |
130 if (e.thread != NULL) { |
135 out->print("Thread " INTPTR_FORMAT " ", e.thread); |
131 out->print("Thread " INTPTR_FORMAT " ", e.thread); |
136 } |
132 } |
137 print(out, e.data); |
133 print(out, e.data); |
138 } |
134 } |
153 StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {} |
149 StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {} |
154 |
150 |
155 void logv(Thread* thread, const char* format, va_list ap) { |
151 void logv(Thread* thread, const char* format, va_list ap) { |
156 if (!should_log()) return; |
152 if (!should_log()) return; |
157 |
153 |
158 jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; |
154 double timestamp = fetch_timestamp(); |
159 MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); |
155 MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); |
160 int index = compute_log_index(); |
156 int index = compute_log_index(); |
161 _records[index].thread = thread; |
157 _records[index].thread = thread; |
162 _records[index].timestamp = timestamp; |
158 _records[index].timestamp = timestamp; |
163 _records[index].data.printv(format, ap); |
159 _records[index].data.printv(format, ap); |
191 static StringEventLog* _deopt_messages; |
187 static StringEventLog* _deopt_messages; |
192 |
188 |
193 public: |
189 public: |
194 static void print_all(outputStream* out); |
190 static void print_all(outputStream* out); |
195 |
191 |
196 static void print() { |
192 // Dump all events to the tty |
197 print_all(tty); |
193 static void print(); |
198 } |
|
199 |
194 |
200 // Logs a generic message with timestamp and format as printf. |
195 // Logs a generic message with timestamp and format as printf. |
201 static void log(Thread* thread, const char* format, ...); |
196 static void log(Thread* thread, const char* format, ...); |
202 |
197 |
203 // Log exception related message |
198 // Log exception related message |
253 template <class T> |
248 template <class T> |
254 inline void EventLogBase<T>::print_log_impl(outputStream* out) { |
249 inline void EventLogBase<T>::print_log_impl(outputStream* out) { |
255 out->print_cr("%s (%d events):", _name, _count); |
250 out->print_cr("%s (%d events):", _name, _count); |
256 if (_count == 0) { |
251 if (_count == 0) { |
257 out->print_cr("No events"); |
252 out->print_cr("No events"); |
|
253 out->cr(); |
258 return; |
254 return; |
259 } |
255 } |
260 |
256 |
261 if (_count < _length) { |
257 if (_count < _length) { |
262 for (int i = 0; i < _count; i++) { |
258 for (int i = 0; i < _count; i++) { |