Mercurial > hg > truffle
comparison src/share/vm/utilities/events.hpp @ 4875:379b22e03c32
Merge
author | jcoomes |
---|---|
date | Fri, 03 Feb 2012 12:08:55 -0800 |
parents | aa3d708d67c4 |
children | 09d00c18e323 |
comparison
equal
deleted
inserted
replaced
4866:527cf36f4a20 | 4875:379b22e03c32 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
24 | 24 |
25 #ifndef SHARE_VM_UTILITIES_EVENTS_HPP | 25 #ifndef SHARE_VM_UTILITIES_EVENTS_HPP |
26 #define SHARE_VM_UTILITIES_EVENTS_HPP | 26 #define SHARE_VM_UTILITIES_EVENTS_HPP |
27 | 27 |
28 #include "memory/allocation.hpp" | 28 #include "memory/allocation.hpp" |
29 #include "runtime/mutexLocker.hpp" | |
30 #include "runtime/thread.hpp" | |
29 #include "utilities/top.hpp" | 31 #include "utilities/top.hpp" |
32 #include "utilities/vmError.hpp" | |
30 | 33 |
31 // 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. |
32 // This facility is extremly useful for post-mortem debugging. The eventlog | 35 // This facility is extremly useful for post-mortem debugging. The eventlog |
33 // often provides crucial information about events leading up to the crash. | 36 // often provides crucial information about events leading up to the crash. |
34 // | 37 // |
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 |