Mercurial > hg > truffle
annotate src/share/vm/utilities/debug.cpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | 2f644f85485d |
rev | line source |
---|---|
0 | 1 /* |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
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 | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "code/codeCache.hpp" | |
28 #include "code/icBuffer.hpp" | |
29 #include "code/nmethod.hpp" | |
30 #include "code/vtableStubs.hpp" | |
31 #include "compiler/compileBroker.hpp" | |
32 #include "compiler/disassembler.hpp" | |
33 #include "gc_implementation/shared/markSweep.hpp" | |
34 #include "gc_interface/collectedHeap.hpp" | |
35 #include "interpreter/bytecodeHistogram.hpp" | |
36 #include "interpreter/interpreter.hpp" | |
37 #include "memory/resourceArea.hpp" | |
38 #include "memory/universe.hpp" | |
39 #include "oops/oop.inline.hpp" | |
40 #include "prims/privilegedStack.hpp" | |
41 #include "runtime/arguments.hpp" | |
42 #include "runtime/frame.hpp" | |
43 #include "runtime/java.hpp" | |
44 #include "runtime/sharedRuntime.hpp" | |
45 #include "runtime/stubCodeGenerator.hpp" | |
46 #include "runtime/stubRoutines.hpp" | |
47 #include "runtime/vframe.hpp" | |
48 #include "services/heapDumper.hpp" | |
49 #include "utilities/defaultStream.hpp" | |
50 #include "utilities/events.hpp" | |
51 #include "utilities/top.hpp" | |
52 #include "utilities/vmError.hpp" | |
53 #ifdef TARGET_OS_FAMILY_linux | |
54 # include "os_linux.inline.hpp" | |
55 # include "thread_linux.inline.hpp" | |
56 #endif | |
57 #ifdef TARGET_OS_FAMILY_solaris | |
58 # include "os_solaris.inline.hpp" | |
59 # include "thread_solaris.inline.hpp" | |
60 #endif | |
61 #ifdef TARGET_OS_FAMILY_windows | |
62 # include "os_windows.inline.hpp" | |
63 # include "thread_windows.inline.hpp" | |
64 #endif | |
0 | 65 |
66 #ifndef ASSERT | |
67 # ifdef _DEBUG | |
68 // NOTE: don't turn the lines below into a comment -- if you're getting | |
69 // a compile error here, change the settings to define ASSERT | |
70 ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging | |
71 functions that do not slow down the system too much and thus can be left in optimized code. | |
72 On the other hand, the code should not be included in a production version. | |
73 # endif // _DEBUG | |
74 #endif // ASSERT | |
75 | |
76 | |
77 #ifdef _DEBUG | |
78 # ifndef ASSERT | |
79 configuration error: ASSERT must be defined in debug version | |
80 # endif // ASSERT | |
81 #endif // _DEBUG | |
82 | |
83 | |
84 #ifdef PRODUCT | |
85 # if -defined _DEBUG || -defined ASSERT | |
86 configuration error: ASSERT et al. must not be defined in PRODUCT version | |
87 # endif | |
88 #endif // PRODUCT | |
89 | |
90 | |
91 void warning(const char* format, ...) { | |
1870
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
92 if (PrintWarnings) { |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
93 // In case error happens before init or during shutdown |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
94 if (tty == NULL) ostream_init(); |
0 | 95 |
1870
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
96 tty->print("%s warning: ", VM_Version::vm_name()); |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
97 va_list ap; |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
98 va_start(ap, format); |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
99 tty->vprint_cr(format, ap); |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
100 va_end(ap); |
c77b5c592eab
6392697: Additional flag needed to supress Hotspot warning messages
kamg
parents:
1775
diff
changeset
|
101 } |
0 | 102 if (BreakAtWarning) BREAKPOINT; |
103 } | |
104 | |
105 #ifndef PRODUCT | |
106 | |
107 #define is_token_break(ch) (isspace(ch) || (ch) == ',') | |
108 | |
109 static const char* last_file_name = NULL; | |
110 static int last_line_no = -1; | |
111 | |
112 // assert/guarantee/... may happen very early during VM initialization. | |
113 // Don't rely on anything that is initialized by Threads::create_vm(). For | |
114 // example, don't use tty. | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
115 bool error_is_suppressed(const char* file_name, int line_no) { |
0 | 116 // The following 1-element cache requires that passed-in |
117 // file names are always only constant literals. | |
118 if (file_name == last_file_name && line_no == last_line_no) return true; | |
119 | |
120 int file_name_len = (int)strlen(file_name); | |
121 char separator = os::file_separator()[0]; | |
122 const char* base_name = strrchr(file_name, separator); | |
123 if (base_name == NULL) | |
124 base_name = file_name; | |
125 | |
126 // scan the SuppressErrorAt option | |
127 const char* cp = SuppressErrorAt; | |
128 for (;;) { | |
129 const char* sfile; | |
130 int sfile_len; | |
131 int sline; | |
132 bool noisy; | |
133 while ((*cp) != '\0' && is_token_break(*cp)) cp++; | |
134 if ((*cp) == '\0') break; | |
135 sfile = cp; | |
136 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; | |
137 sfile_len = cp - sfile; | |
138 if ((*cp) == ':') cp++; | |
139 sline = 0; | |
140 while ((*cp) != '\0' && isdigit(*cp)) { | |
141 sline *= 10; | |
142 sline += (*cp) - '0'; | |
143 cp++; | |
144 } | |
145 // "file:line!" means the assert suppression is not silent | |
146 noisy = ((*cp) == '!'); | |
147 while ((*cp) != '\0' && !is_token_break(*cp)) cp++; | |
148 // match the line | |
149 if (sline != 0) { | |
150 if (sline != line_no) continue; | |
151 } | |
152 // match the file | |
153 if (sfile_len > 0) { | |
154 const char* look = file_name; | |
155 const char* look_max = file_name + file_name_len - sfile_len; | |
156 const char* foundp; | |
157 bool match = false; | |
158 while (!match | |
159 && (foundp = strchr(look, sfile[0])) != NULL | |
160 && foundp <= look_max) { | |
161 match = true; | |
162 for (int i = 1; i < sfile_len; i++) { | |
163 if (sfile[i] != foundp[i]) { | |
164 match = false; | |
165 break; | |
166 } | |
167 } | |
168 look = foundp + 1; | |
169 } | |
170 if (!match) continue; | |
171 } | |
172 // got a match! | |
173 if (noisy) { | |
174 fdStream out(defaultStream::output_fd()); | |
175 out.print_raw("[error suppressed at "); | |
176 out.print_raw(base_name); | |
177 char buf[16]; | |
178 jio_snprintf(buf, sizeof(buf), ":%d]", line_no); | |
179 out.print_raw_cr(buf); | |
180 } else { | |
181 // update 1-element cache for fast silent matches | |
182 last_file_name = file_name; | |
183 last_line_no = line_no; | |
184 } | |
185 return true; | |
186 } | |
187 | |
188 if (!is_error_reported()) { | |
189 // print a friendly hint: | |
190 fdStream out(defaultStream::output_fd()); | |
191 out.print_raw_cr("# To suppress the following error report, specify this argument"); | |
192 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); | |
193 out.print_raw (base_name); | |
194 char buf[16]; | |
195 jio_snprintf(buf, sizeof(buf), ":%d", line_no); | |
196 out.print_raw_cr(buf); | |
197 } | |
198 return false; | |
199 } | |
200 | |
201 #undef is_token_break | |
202 | |
203 #else | |
204 | |
205 // Place-holder for non-existent suppression check: | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
206 #define error_is_suppressed(file_name, line_no) (false) |
0 | 207 |
208 #endif //PRODUCT | |
209 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
210 void report_vm_error(const char* file, int line, const char* error_msg, |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
211 const char* detail_msg) |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
212 { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
213 if (Debugging || error_is_suppressed(file, line)) return; |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
214 Thread* const thread = ThreadLocalStorage::get_thread_slow(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
215 VMError err(thread, file, line, error_msg, detail_msg); |
0 | 216 err.report_and_die(); |
217 } | |
218 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
219 void report_fatal(const char* file, int line, const char* message) |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
220 { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
221 report_vm_error(file, line, "fatal error", message); |
0 | 222 } |
223 | |
224 // Used by report_vm_out_of_memory to detect recursion. | |
225 static jint _exiting_out_of_mem = 0; | |
226 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
227 void report_vm_out_of_memory(const char* file, int line, size_t size, |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
228 const char* message) { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
229 if (Debugging || error_is_suppressed(file, line)) return; |
0 | 230 |
231 // We try to gather additional information for the first out of memory | |
232 // error only; gathering additional data might cause an allocation and a | |
233 // recursive out_of_memory condition. | |
234 | |
235 const jint exiting = 1; | |
236 // If we succeed in changing the value, we're the first one in. | |
237 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; | |
238 | |
239 if (first_time_here) { | |
240 Thread* thread = ThreadLocalStorage::get_thread_slow(); | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
241 VMError(thread, file, line, size, message).report_and_die(); |
0 | 242 } |
227
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
243 |
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
244 // Dump core and abort |
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
245 vm_abort(true); |
0 | 246 } |
247 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
248 void report_should_not_call(const char* file, int line) { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
249 report_vm_error(file, line, "ShouldNotCall()"); |
0 | 250 } |
251 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
252 void report_should_not_reach_here(const char* file, int line) { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
253 report_vm_error(file, line, "ShouldNotReachHere()"); |
0 | 254 } |
255 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
256 void report_unimplemented(const char* file, int line) { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
257 report_vm_error(file, line, "Unimplemented()"); |
0 | 258 } |
259 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
260 void report_untested(const char* file, int line, const char* message) { |
0 | 261 #ifndef PRODUCT |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
262 warning("Untested: %s in %s: %d\n", message, file, line); |
0 | 263 #endif // PRODUCT |
264 } | |
265 | |
266 void report_java_out_of_memory(const char* message) { | |
267 static jint out_of_memory_reported = 0; | |
268 | |
269 // A number of threads may attempt to report OutOfMemoryError at around the | |
270 // same time. To avoid dumping the heap or executing the data collection | |
271 // commands multiple times we just do it once when the first threads reports | |
272 // the error. | |
273 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { | |
274 // create heap dump before OnOutOfMemoryError commands are executed | |
275 if (HeapDumpOnOutOfMemoryError) { | |
276 tty->print_cr("java.lang.OutOfMemoryError: %s", message); | |
1775
30f67acf635d
6765718: Indicate which thread throwing OOME when generating the heap dump at OOME
thurka
parents:
1681
diff
changeset
|
277 HeapDumper::dump_heap_from_oome(); |
0 | 278 } |
279 | |
280 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { | |
281 VMError err(message); | |
282 err.report_java_out_of_memory(); | |
283 } | |
284 } | |
285 } | |
286 | |
287 | |
288 extern "C" void ps(); | |
289 | |
290 static bool error_reported = false; | |
291 | |
292 // call this when the VM is dying--it might loosen some asserts | |
293 void set_error_reported() { | |
294 error_reported = true; | |
295 } | |
296 | |
297 bool is_error_reported() { | |
298 return error_reported; | |
299 } | |
300 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
301 #ifndef PRODUCT |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
302 #include <signal.h> |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
303 |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
304 void test_error_handler(size_t test_num) |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
305 { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
306 if (test_num == 0) return; |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
307 |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
308 // If asserts are disabled, use the corresponding guarantee instead. |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
309 size_t n = test_num; |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
310 NOT_DEBUG(if (n <= 2) n += 2); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
311 |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
312 const char* const str = "hello"; |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
313 const size_t num = (size_t)os::vm_page_size(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
314 |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
315 const char* const eol = os::line_separator(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
316 const char* const msg = "this message should be truncated during formatting"; |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
317 |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
318 // Keep this in sync with test/runtime/6888954/vmerrors.sh. |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
319 switch (n) { |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
320 case 1: assert(str == NULL, "expected null"); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
321 case 2: assert(num == 1023 && *str == 'X', |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
322 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
323 case 3: guarantee(str == NULL, "expected null"); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
324 case 4: guarantee(num == 1023 && *str == 'X', |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
325 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
326 case 5: fatal("expected null"); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
327 case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
328 case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
329 "%s%s# %s%s# %s%s# %s%s# %s%s# " |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
330 "%s%s# %s%s# %s%s# %s%s# %s", |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
331 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
332 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
333 msg, eol, msg, eol, msg, eol, msg, eol, msg)); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
334 case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate"); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
335 case 9: ShouldNotCallThis(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
336 case 10: ShouldNotReachHere(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
337 case 11: Unimplemented(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
338 // This is last because it does not generate an hs_err* file on Windows. |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
339 case 12: os::signal_raise(SIGSEGV); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
340 |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
341 default: ShouldNotReachHere(); |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
342 } |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
343 } |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
344 #endif // #ifndef PRODUCT |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
989
diff
changeset
|
345 |
0 | 346 // ------ helper functions for debugging go here ------------ |
347 | |
348 #ifndef PRODUCT | |
349 // All debug entries should be wrapped with a stack allocated | |
350 // Command object. It makes sure a resource mark is set and | |
351 // flushes the logfile to prevent file sharing problems. | |
352 | |
353 class Command : public StackObj { | |
354 private: | |
355 ResourceMark rm; | |
356 ResetNoHandleMark rnhm; | |
357 HandleMark hm; | |
358 bool debug_save; | |
359 public: | |
360 static int level; | |
361 Command(const char* str) { | |
362 debug_save = Debugging; | |
363 Debugging = true; | |
364 if (level++ > 0) return; | |
365 tty->cr(); | |
366 tty->print_cr("\"Executing %s\"", str); | |
367 } | |
368 | |
369 ~Command() { tty->flush(); Debugging = debug_save; level--; } | |
370 }; | |
371 | |
372 int Command::level = 0; | |
373 | |
374 extern "C" void blob(CodeBlob* cb) { | |
375 Command c("blob"); | |
376 cb->print(); | |
377 } | |
378 | |
379 | |
380 extern "C" void dump_vtable(address p) { | |
381 Command c("dump_vtable"); | |
382 klassOop k = (klassOop)p; | |
383 instanceKlass::cast(k)->vtable()->print(); | |
384 } | |
385 | |
386 | |
387 extern "C" void nm(intptr_t p) { | |
388 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) | |
389 Command c("nm"); | |
390 CodeBlob* cb = CodeCache::find_blob((address)p); | |
391 if (cb == NULL) { | |
392 tty->print_cr("NULL"); | |
393 } else { | |
394 cb->print(); | |
395 } | |
396 } | |
397 | |
398 | |
399 extern "C" void disnm(intptr_t p) { | |
400 Command c("disnm"); | |
401 CodeBlob* cb = CodeCache::find_blob((address) p); | |
402 cb->print(); | |
403 Disassembler::decode(cb); | |
404 } | |
405 | |
406 | |
407 extern "C" void printnm(intptr_t p) { | |
408 char buffer[256]; | |
409 sprintf(buffer, "printnm: " INTPTR_FORMAT, p); | |
410 Command c(buffer); | |
411 CodeBlob* cb = CodeCache::find_blob((address) p); | |
412 if (cb->is_nmethod()) { | |
413 nmethod* nm = (nmethod*)cb; | |
414 nm->print_nmethod(true); | |
415 } | |
416 } | |
417 | |
418 | |
419 extern "C" void universe() { | |
420 Command c("universe"); | |
421 Universe::print(); | |
422 } | |
423 | |
424 | |
425 extern "C" void verify() { | |
426 // try to run a verify on the entire system | |
427 // note: this may not be safe if we're not at a safepoint; for debugging, | |
428 // this manipulates the safepoint settings to avoid assertion failures | |
429 Command c("universe verify"); | |
430 bool safe = SafepointSynchronize::is_at_safepoint(); | |
431 if (!safe) { | |
432 tty->print_cr("warning: not at safepoint -- verify may fail"); | |
433 SafepointSynchronize::set_is_at_safepoint(); | |
434 } | |
435 // Ensure Eden top is correct before verification | |
436 Universe::heap()->prepare_for_verify(); | |
437 Universe::verify(true); | |
438 if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); | |
439 } | |
440 | |
441 | |
442 extern "C" void pp(void* p) { | |
443 Command c("pp"); | |
444 FlagSetting fl(PrintVMMessages, true); | |
445 if (Universe::heap()->is_in(p)) { | |
446 oop obj = oop(p); | |
447 obj->print(); | |
448 } else { | |
449 tty->print("%#p", p); | |
450 } | |
451 } | |
452 | |
453 | |
454 // pv: print vm-printable object | |
455 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } | |
456 extern "C" void findpc(intptr_t x); | |
457 | |
458 extern "C" void ps() { // print stack | |
459 Command c("ps"); | |
460 | |
461 | |
462 // Prints the stack of the current Java thread | |
463 JavaThread* p = JavaThread::active(); | |
464 tty->print(" for thread: "); | |
465 p->print(); | |
466 tty->cr(); | |
467 | |
468 if (p->has_last_Java_frame()) { | |
469 // If the last_Java_fp is set we are in C land and | |
470 // can call the standard stack_trace function. | |
471 p->trace_stack(); | |
472 } else { | |
473 frame f = os::current_frame(); | |
474 RegisterMap reg_map(p); | |
475 f = f.sender(®_map); | |
476 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); | |
477 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); | |
478 pd_ps(f); | |
479 } | |
480 | |
481 } | |
482 | |
483 | |
484 extern "C" void psf() { // print stack frames | |
485 { | |
486 Command c("psf"); | |
487 JavaThread* p = JavaThread::active(); | |
488 tty->print(" for thread: "); | |
489 p->print(); | |
490 tty->cr(); | |
491 if (p->has_last_Java_frame()) { | |
492 p->trace_frames(); | |
493 } | |
494 } | |
495 } | |
496 | |
497 | |
498 extern "C" void threads() { | |
499 Command c("threads"); | |
500 Threads::print(false, true); | |
501 } | |
502 | |
503 | |
504 extern "C" void psd() { | |
505 Command c("psd"); | |
506 SystemDictionary::print(); | |
507 } | |
508 | |
509 | |
510 extern "C" void safepoints() { | |
511 Command c("safepoints"); | |
512 SafepointSynchronize::print_state(); | |
513 } | |
514 | |
515 | |
516 extern "C" void pss() { // print all stacks | |
517 Command c("pss"); | |
518 Threads::print(true, true); | |
519 } | |
520 | |
521 | |
522 extern "C" void debug() { // to set things up for compiler debugging | |
523 Command c("debug"); | |
524 WizardMode = true; | |
525 PrintVMMessages = PrintCompilation = true; | |
526 PrintInlining = PrintAssembly = true; | |
527 tty->flush(); | |
528 } | |
529 | |
530 | |
531 extern "C" void ndebug() { // undo debug() | |
532 Command c("ndebug"); | |
533 PrintCompilation = false; | |
534 PrintInlining = PrintAssembly = false; | |
535 tty->flush(); | |
536 } | |
537 | |
538 | |
539 extern "C" void flush() { | |
540 Command c("flush"); | |
541 tty->flush(); | |
542 } | |
543 | |
544 | |
545 extern "C" void events() { | |
546 Command c("events"); | |
547 Events::print_last(tty, 50); | |
548 } | |
549 | |
550 | |
551 extern "C" void nevents(int n) { | |
552 Command c("events"); | |
553 Events::print_last(tty, n); | |
554 } | |
555 | |
556 | |
557 // Given a heap address that was valid before the most recent GC, if | |
558 // the oop that used to contain it is still live, prints the new | |
559 // location of the oop and the address. Useful for tracking down | |
560 // certain kinds of naked oop and oop map bugs. | |
561 extern "C" void pnl(intptr_t old_heap_addr) { | |
562 // Print New Location of old heap address | |
563 Command c("pnl"); | |
564 #ifndef VALIDATE_MARK_SWEEP | |
565 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled"); | |
566 #else | |
567 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr); | |
568 #endif | |
569 } | |
570 | |
571 | |
572 extern "C" methodOop findm(intptr_t pc) { | |
573 Command c("findm"); | |
574 nmethod* nm = CodeCache::find_nmethod((address)pc); | |
575 return (nm == NULL) ? (methodOop)NULL : nm->method(); | |
576 } | |
577 | |
578 | |
579 extern "C" nmethod* findnm(intptr_t addr) { | |
580 Command c("findnm"); | |
581 return CodeCache::find_nmethod((address)addr); | |
582 } | |
583 | |
584 static address same_page(address x, address y) { | |
585 intptr_t page_bits = -os::vm_page_size(); | |
586 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) { | |
587 return x; | |
588 } else if (x > y) { | |
589 return (address)(intptr_t(y) | ~page_bits) + 1; | |
590 } else { | |
591 return (address)(intptr_t(y) & page_bits); | |
592 } | |
593 } | |
594 | |
595 class LookForRefInGenClosure : public OopsInGenClosure { | |
596 public: | |
597 oop target; | |
598 void do_oop(oop* o) { | |
599 if (o != NULL && *o == target) { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
600 tty->print_cr(INTPTR_FORMAT, o); |
0 | 601 } |
602 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
603 void do_oop(narrowOop* o) { ShouldNotReachHere(); } |
0 | 604 }; |
605 | |
606 | |
607 class LookForRefInObjectClosure : public ObjectClosure { | |
608 private: | |
609 LookForRefInGenClosure look_in_object; | |
610 public: | |
611 LookForRefInObjectClosure(oop target) { look_in_object.target = target; } | |
612 void do_object(oop obj) { | |
613 obj->oop_iterate(&look_in_object); | |
614 } | |
615 }; | |
616 | |
617 | |
618 static void findref(intptr_t x) { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
619 CollectedHeap *ch = Universe::heap(); |
0 | 620 LookForRefInGenClosure lookFor; |
621 lookFor.target = (oop) x; | |
622 LookForRefInObjectClosure look_in_object((oop) x); | |
623 | |
624 tty->print_cr("Searching heap:"); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
625 ch->object_iterate(&look_in_object); |
0 | 626 |
627 tty->print_cr("Searching strong roots:"); | |
628 Universe::oops_do(&lookFor, false); | |
629 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
630 Threads::oops_do(&lookFor, NULL); |
0 | 631 ObjectSynchronizer::oops_do(&lookFor); |
632 //FlatProfiler::oops_do(&lookFor); | |
633 SystemDictionary::oops_do(&lookFor); | |
634 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
635 tty->print_cr("Searching code cache:"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
636 CodeCache::oops_do(&lookFor); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
637 |
0 | 638 tty->print_cr("Done."); |
639 } | |
640 | |
641 class FindClassObjectClosure: public ObjectClosure { | |
642 private: | |
643 const char* _target; | |
644 public: | |
645 FindClassObjectClosure(const char name[]) { _target = name; } | |
646 | |
647 virtual void do_object(oop obj) { | |
648 if (obj->is_klass()) { | |
649 Klass* k = klassOop(obj)->klass_part(); | |
650 if (k->name() != NULL) { | |
651 ResourceMark rm; | |
652 const char* ext = k->external_name(); | |
653 if ( strcmp(_target, ext) == 0 ) { | |
654 tty->print_cr("Found " INTPTR_FORMAT, obj); | |
655 obj->print(); | |
656 } | |
657 } | |
658 } | |
659 } | |
660 }; | |
661 | |
662 // | |
663 extern "C" void findclass(const char name[]) { | |
664 Command c("findclass"); | |
665 if (name != NULL) { | |
666 tty->print_cr("Finding class %s -> ", name); | |
667 FindClassObjectClosure srch(name); | |
668 Universe::heap()->permanent_object_iterate(&srch); | |
669 } | |
670 } | |
671 | |
672 // Another interface that isn't ambiguous in dbx. | |
673 // Can we someday rename the other find to hsfind? | |
674 extern "C" void hsfind(intptr_t x) { | |
675 Command c("hsfind"); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
676 os::print_location(tty, x, false); |
0 | 677 } |
678 | |
679 | |
680 extern "C" void hsfindref(intptr_t x) { | |
681 Command c("hsfindref"); | |
682 findref(x); | |
683 } | |
684 | |
685 extern "C" void find(intptr_t x) { | |
686 Command c("find"); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
687 os::print_location(tty, x, false); |
0 | 688 } |
689 | |
690 | |
691 extern "C" void findpc(intptr_t x) { | |
692 Command c("findpc"); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
693 os::print_location(tty, x, true); |
0 | 694 } |
695 | |
696 | |
697 // int versions of all methods to avoid having to type type casts in the debugger | |
698 | |
699 void pp(intptr_t p) { pp((void*)p); } | |
700 void pp(oop p) { pp((void*)p); } | |
701 | |
702 void help() { | |
703 Command c("help"); | |
704 tty->print_cr("basic"); | |
705 tty->print_cr(" pp(void* p) - try to make sense of p"); | |
706 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); | |
707 tty->print_cr(" ps() - print current thread stack"); | |
708 tty->print_cr(" pss() - print all thread stacks"); | |
709 tty->print_cr(" pm(int pc) - print methodOop given compiled PC"); | |
710 tty->print_cr(" findm(intptr_t pc) - finds methodOop"); | |
711 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); | |
712 | |
713 tty->print_cr("misc."); | |
714 tty->print_cr(" flush() - flushes the log file"); | |
715 tty->print_cr(" events() - dump last 50 events"); | |
716 | |
717 | |
718 tty->print_cr("compiler debugging"); | |
719 tty->print_cr(" debug() - to set things up for compiler debugging"); | |
720 tty->print_cr(" ndebug() - undo debug"); | |
721 } | |
722 | |
723 #if 0 | |
724 | |
725 // BobV's command parser for debugging on windows when nothing else works. | |
726 | |
727 enum CommandID { | |
728 CMDID_HELP, | |
729 CMDID_QUIT, | |
730 CMDID_HSFIND, | |
731 CMDID_PSS, | |
732 CMDID_PS, | |
733 CMDID_PSF, | |
734 CMDID_FINDM, | |
735 CMDID_FINDNM, | |
736 CMDID_PP, | |
737 CMDID_BPT, | |
738 CMDID_EXIT, | |
739 CMDID_VERIFY, | |
740 CMDID_THREADS, | |
741 CMDID_ILLEGAL = 99 | |
742 }; | |
743 | |
744 struct CommandParser { | |
745 char *name; | |
746 CommandID code; | |
747 char *description; | |
748 }; | |
749 | |
750 struct CommandParser CommandList[] = { | |
751 (char *)"help", CMDID_HELP, " Dump this list", | |
752 (char *)"quit", CMDID_QUIT, " Return from this routine", | |
753 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", | |
754 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", | |
755 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", | |
756 (char *)"psf", CMDID_PSF, " Print All Stack Frames", | |
757 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC", | |
758 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", | |
759 (char *)"pp", CMDID_PP, " Find out something about a pointer", | |
760 (char *)"break", CMDID_BPT, " Execute a breakpoint", | |
761 (char *)"exitvm", CMDID_EXIT, "Exit the VM", | |
762 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", | |
763 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", | |
764 (char *)0, CMDID_ILLEGAL | |
765 }; | |
766 | |
767 | |
768 // get_debug_command() | |
769 // | |
770 // Read a command from standard input. | |
771 // This is useful when you have a debugger | |
772 // which doesn't support calling into functions. | |
773 // | |
774 void get_debug_command() | |
775 { | |
776 ssize_t count; | |
777 int i,j; | |
778 bool gotcommand; | |
779 intptr_t addr; | |
780 char buffer[256]; | |
781 nmethod *nm; | |
782 methodOop m; | |
783 | |
784 tty->print_cr("You have entered the diagnostic command interpreter"); | |
785 tty->print("The supported commands are:\n"); | |
786 for ( i=0; ; i++ ) { | |
787 if ( CommandList[i].code == CMDID_ILLEGAL ) | |
788 break; | |
789 tty->print_cr(" %s \n", CommandList[i].name ); | |
790 } | |
791 | |
792 while ( 1 ) { | |
793 gotcommand = false; | |
794 tty->print("Please enter a command: "); | |
795 count = scanf("%s", buffer) ; | |
796 if ( count >=0 ) { | |
797 for ( i=0; ; i++ ) { | |
798 if ( CommandList[i].code == CMDID_ILLEGAL ) { | |
799 if (!gotcommand) tty->print("Invalid command, please try again\n"); | |
800 break; | |
801 } | |
802 if ( strcmp(buffer, CommandList[i].name) == 0 ) { | |
803 gotcommand = true; | |
804 switch ( CommandList[i].code ) { | |
805 case CMDID_PS: | |
806 ps(); | |
807 break; | |
808 case CMDID_PSS: | |
809 pss(); | |
810 break; | |
811 case CMDID_PSF: | |
812 psf(); | |
813 break; | |
814 case CMDID_FINDM: | |
815 tty->print("Please enter the hex addr to pass to findm: "); | |
816 scanf("%I64X", &addr); | |
817 m = (methodOop)findm(addr); | |
818 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); | |
819 break; | |
820 case CMDID_FINDNM: | |
821 tty->print("Please enter the hex addr to pass to findnm: "); | |
822 scanf("%I64X", &addr); | |
823 nm = (nmethod*)findnm(addr); | |
824 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); | |
825 break; | |
826 case CMDID_PP: | |
827 tty->print("Please enter the hex addr to pass to pp: "); | |
828 scanf("%I64X", &addr); | |
829 pp((void*)addr); | |
830 break; | |
831 case CMDID_EXIT: | |
832 exit(0); | |
833 case CMDID_HELP: | |
834 tty->print("Here are the supported commands: "); | |
835 for ( j=0; ; j++ ) { | |
836 if ( CommandList[j].code == CMDID_ILLEGAL ) | |
837 break; | |
838 tty->print_cr(" %s -- %s\n", CommandList[j].name, | |
839 CommandList[j].description ); | |
840 } | |
841 break; | |
842 case CMDID_QUIT: | |
843 return; | |
844 break; | |
845 case CMDID_BPT: | |
846 BREAKPOINT; | |
847 break; | |
848 case CMDID_VERIFY: | |
849 verify();; | |
850 break; | |
851 case CMDID_THREADS: | |
852 threads();; | |
853 break; | |
854 case CMDID_HSFIND: | |
855 tty->print("Please enter the hex addr to pass to hsfind: "); | |
856 scanf("%I64X", &addr); | |
857 tty->print("Calling hsfind(0x%I64X)\n", addr); | |
858 hsfind(addr); | |
859 break; | |
860 default: | |
861 case CMDID_ILLEGAL: | |
862 break; | |
863 } | |
864 } | |
865 } | |
866 } | |
867 } | |
868 } | |
869 #endif | |
870 | |
871 #endif // PRODUCT |