45 // |
48 // |
46 // IMPLEMENTATION RESTRICTION: |
49 // IMPLEMENTATION RESTRICTION: |
47 // Max 3 arguments are saved for each logged event. |
50 // Max 3 arguments are saved for each logged event. |
48 // |
51 // |
49 |
52 |
|
53 // 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 |
|
55 // for completeness. Normally the templated EventLogBase would be |
|
56 // subclassed to provide different log types. |
|
57 class EventLog : public CHeapObj { |
|
58 friend class Events; |
|
59 |
|
60 private: |
|
61 EventLog* _next; |
|
62 |
|
63 EventLog* next() const { return _next; } |
|
64 |
|
65 public: |
|
66 // Automatically registers the log so that it will be printed during |
|
67 // crashes. |
|
68 EventLog(); |
|
69 |
|
70 virtual void print_log_on(outputStream* out) = 0; |
|
71 }; |
|
72 |
|
73 |
|
74 // A templated subclass of EventLog that provides basic ring buffer |
|
75 // functionality. Most event loggers should subclass this, possibly |
|
76 // providing a more featureful log function if the existing copy |
|
77 // semantics aren't appropriate. The name is used as the label of the |
|
78 // log when it is dumped during a crash. |
|
79 template <class T> class EventLogBase : public EventLog { |
|
80 template <class X> class EventRecord { |
|
81 public: |
|
82 jlong timestamp; |
|
83 Thread* thread; |
|
84 X data; |
|
85 }; |
|
86 |
|
87 protected: |
|
88 Mutex _mutex; |
|
89 const char* _name; |
|
90 int _length; |
|
91 int _index; |
|
92 int _count; |
|
93 EventRecord<T>* _records; |
|
94 |
|
95 public: |
|
96 EventLogBase<T>(const char* name, int length = LogEventsBufferEntries): |
|
97 _name(name), |
|
98 _length(length), |
|
99 _count(0), |
|
100 _index(0), |
|
101 _mutex(Mutex::event, name) { |
|
102 _records = new EventRecord<T>[length]; |
|
103 } |
|
104 |
|
105 // 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 |
|
107 // while mutex is held. |
|
108 int compute_log_index() { |
|
109 int index = _index; |
|
110 if (_count < _length) _count++; |
|
111 _index++; |
|
112 if (_index >= _length) _index = 0; |
|
113 return index; |
|
114 } |
|
115 |
|
116 bool should_log() { |
|
117 // Don't bother adding new entries when we're crashing. This also |
|
118 // avoids mutating the ring buffer when printing the log. |
|
119 return !VMError::fatal_error_in_progress(); |
|
120 } |
|
121 |
|
122 // Print the contents of the log |
|
123 void print_log_on(outputStream* out); |
|
124 |
|
125 private: |
|
126 void print_log_impl(outputStream* out); |
|
127 |
|
128 // Print a single element. A templated implementation might need to |
|
129 // be declared by subclasses. |
|
130 void print(outputStream* out, T& e); |
|
131 |
|
132 void print(outputStream* out, EventRecord<T>& e) { |
|
133 out->print("Event: " INT64_FORMAT " ", e.timestamp); |
|
134 if (e.thread != NULL) { |
|
135 out->print("Thread " INTPTR_FORMAT " ", e.thread); |
|
136 } |
|
137 print(out, e.data); |
|
138 } |
|
139 }; |
|
140 |
|
141 // A simple wrapper class for fixed size text messages. |
|
142 class StringLogMessage : public FormatBuffer<132> { |
|
143 public: |
|
144 // Wrap this buffer in a stringStream. |
|
145 stringStream stream() { |
|
146 return stringStream(_buf, sizeof(_buf)); |
|
147 } |
|
148 }; |
|
149 |
|
150 // A simple ring buffer of fixed size text messages. |
|
151 class StringEventLog : public EventLogBase<StringLogMessage> { |
|
152 public: |
|
153 StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {} |
|
154 |
|
155 void logv(Thread* thread, const char* format, va_list ap) { |
|
156 if (!should_log()) return; |
|
157 |
|
158 jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; |
|
159 MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); |
|
160 int index = compute_log_index(); |
|
161 _records[index].thread = thread; |
|
162 _records[index].timestamp = timestamp; |
|
163 _records[index].data.printv(format, ap); |
|
164 } |
|
165 |
|
166 void log(Thread* thread, const char* format, ...) { |
|
167 va_list ap; |
|
168 va_start(ap, format); |
|
169 logv(thread, format, ap); |
|
170 va_end(ap); |
|
171 } |
|
172 |
|
173 }; |
|
174 |
|
175 |
|
176 |
50 class Events : AllStatic { |
177 class Events : AllStatic { |
51 public: |
178 friend class EventLog; |
52 // Logs an event, format as printf |
179 |
53 static void log(const char* format, ...) PRODUCT_RETURN; |
180 private: |
54 |
181 static EventLog* _logs; |
55 // Prints all events in the buffer |
182 |
56 static void print_all(outputStream* st) PRODUCT_RETURN; |
183 // A log for generic messages that aren't well categorized. |
57 |
184 static StringEventLog* _messages; |
58 // Prints last number events from the event buffer |
185 |
59 static void print_last(outputStream *st, int number) PRODUCT_RETURN; |
186 // A log for internal exception related messages, like internal |
60 }; |
187 // throws and implicit exceptions. |
61 |
188 static StringEventLog* _exceptions; |
|
189 |
|
190 // Deoptization related messages |
|
191 static StringEventLog* _deopt_messages; |
|
192 |
|
193 public: |
|
194 static void print_all(outputStream* out); |
|
195 |
|
196 static void print() { |
|
197 print_all(tty); |
|
198 } |
|
199 |
|
200 // Logs a generic message with timestamp and format as printf. |
|
201 static void log(Thread* thread, const char* format, ...); |
|
202 |
|
203 // Log exception related message |
|
204 static void log_exception(Thread* thread, const char* format, ...); |
|
205 |
|
206 static void log_deopt_message(Thread* thread, const char* format, ...); |
|
207 |
|
208 // Register default loggers |
|
209 static void init(); |
|
210 }; |
|
211 |
|
212 |
|
213 inline void Events::log(Thread* thread, const char* format, ...) { |
|
214 if (LogEvents) { |
|
215 va_list ap; |
|
216 va_start(ap, format); |
|
217 _messages->logv(thread, format, ap); |
|
218 va_end(ap); |
|
219 } |
|
220 } |
|
221 |
|
222 inline void Events::log_exception(Thread* thread, const char* format, ...) { |
|
223 if (LogEvents) { |
|
224 va_list ap; |
|
225 va_start(ap, format); |
|
226 _exceptions->logv(thread, format, ap); |
|
227 va_end(ap); |
|
228 } |
|
229 } |
|
230 |
|
231 inline void Events::log_deopt_message(Thread* thread, const char* format, ...) { |
|
232 if (LogEvents) { |
|
233 va_list ap; |
|
234 va_start(ap, format); |
|
235 _deopt_messages->logv(thread, format, ap); |
|
236 va_end(ap); |
|
237 } |
|
238 } |
|
239 |
|
240 |
|
241 template <class T> |
|
242 inline void EventLogBase<T>::print_log_on(outputStream* out) { |
|
243 if (ThreadLocalStorage::get_thread_slow() == NULL) { |
|
244 // Not a regular Java thread so don't bother locking |
|
245 print_log_impl(out); |
|
246 } else { |
|
247 MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); |
|
248 print_log_impl(out); |
|
249 } |
|
250 } |
|
251 |
|
252 // Dump the ring buffer entries that current have entries. |
|
253 template <class T> |
|
254 inline void EventLogBase<T>::print_log_impl(outputStream* out) { |
|
255 out->print_cr("%s (%d events):", _name, _count); |
|
256 if (_count == 0) { |
|
257 out->print_cr("No events"); |
|
258 return; |
|
259 } |
|
260 |
|
261 if (_count < _length) { |
|
262 for (int i = 0; i < _count; i++) { |
|
263 print(out, _records[i]); |
|
264 } |
|
265 } else { |
|
266 for (int i = _index; i < _length; i++) { |
|
267 print(out, _records[i]); |
|
268 } |
|
269 for (int i = 0; i < _index; i++) { |
|
270 print(out, _records[i]); |
|
271 } |
|
272 } |
|
273 out->cr(); |
|
274 } |
|
275 |
|
276 // Implement a printing routine for the StringLogMessage |
|
277 template <> |
|
278 inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) { |
|
279 out->print_raw(lm); |
|
280 out->cr(); |
|
281 } |
|
282 |
|
283 // Place markers for the beginning and end up of a set of events. |
|
284 // These end up in the default log. |
62 class EventMark : public StackObj { |
285 class EventMark : public StackObj { |
|
286 StringLogMessage _buffer; |
|
287 |
63 public: |
288 public: |
64 // log a begin event, format as printf |
289 // log a begin event, format as printf |
65 EventMark(const char* format, ...) PRODUCT_RETURN; |
290 EventMark(const char* format, ...); |
66 // log an end event |
291 // log an end event |
67 ~EventMark() PRODUCT_RETURN; |
292 ~EventMark(); |
68 }; |
293 }; |
69 |
|
70 int print_all_events(outputStream *st); |
|
71 |
294 |
72 #endif // SHARE_VM_UTILITIES_EVENTS_HPP |
295 #endif // SHARE_VM_UTILITIES_EVENTS_HPP |