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