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