Mercurial > hg > truffle
annotate src/share/vm/utilities/debug.cpp @ 453:c96030fff130
6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Thu, 20 Nov 2008 16:56:09 -0800 |
parents | 275a3b7ff0d6 |
children | 148e5441d916 |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 1997-2008 Sun Microsystems, Inc. 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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
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, ...) { | |
54 // In case error happens before init or during shutdown | |
55 if (tty == NULL) ostream_init(); | |
56 | |
57 tty->print("%s warning: ", VM_Version::vm_name()); | |
58 va_list ap; | |
59 va_start(ap, format); | |
60 tty->vprint_cr(format, ap); | |
61 va_end(ap); | |
62 if (BreakAtWarning) BREAKPOINT; | |
63 } | |
64 | |
65 #ifndef PRODUCT | |
66 | |
67 #define is_token_break(ch) (isspace(ch) || (ch) == ',') | |
68 | |
69 static const char* last_file_name = NULL; | |
70 static int last_line_no = -1; | |
71 | |
72 // assert/guarantee/... may happen very early during VM initialization. | |
73 // Don't rely on anything that is initialized by Threads::create_vm(). For | |
74 // example, don't use tty. | |
75 bool assert_is_suppressed(const char* file_name, int line_no) { | |
76 // The following 1-element cache requires that passed-in | |
77 // file names are always only constant literals. | |
78 if (file_name == last_file_name && line_no == last_line_no) return true; | |
79 | |
80 int file_name_len = (int)strlen(file_name); | |
81 char separator = os::file_separator()[0]; | |
82 const char* base_name = strrchr(file_name, separator); | |
83 if (base_name == NULL) | |
84 base_name = file_name; | |
85 | |
86 // scan the SuppressErrorAt option | |
87 const char* cp = SuppressErrorAt; | |
88 for (;;) { | |
89 const char* sfile; | |
90 int sfile_len; | |
91 int sline; | |
92 bool noisy; | |
93 while ((*cp) != '\0' && is_token_break(*cp)) cp++; | |
94 if ((*cp) == '\0') break; | |
95 sfile = cp; | |
96 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; | |
97 sfile_len = cp - sfile; | |
98 if ((*cp) == ':') cp++; | |
99 sline = 0; | |
100 while ((*cp) != '\0' && isdigit(*cp)) { | |
101 sline *= 10; | |
102 sline += (*cp) - '0'; | |
103 cp++; | |
104 } | |
105 // "file:line!" means the assert suppression is not silent | |
106 noisy = ((*cp) == '!'); | |
107 while ((*cp) != '\0' && !is_token_break(*cp)) cp++; | |
108 // match the line | |
109 if (sline != 0) { | |
110 if (sline != line_no) continue; | |
111 } | |
112 // match the file | |
113 if (sfile_len > 0) { | |
114 const char* look = file_name; | |
115 const char* look_max = file_name + file_name_len - sfile_len; | |
116 const char* foundp; | |
117 bool match = false; | |
118 while (!match | |
119 && (foundp = strchr(look, sfile[0])) != NULL | |
120 && foundp <= look_max) { | |
121 match = true; | |
122 for (int i = 1; i < sfile_len; i++) { | |
123 if (sfile[i] != foundp[i]) { | |
124 match = false; | |
125 break; | |
126 } | |
127 } | |
128 look = foundp + 1; | |
129 } | |
130 if (!match) continue; | |
131 } | |
132 // got a match! | |
133 if (noisy) { | |
134 fdStream out(defaultStream::output_fd()); | |
135 out.print_raw("[error suppressed at "); | |
136 out.print_raw(base_name); | |
137 char buf[16]; | |
138 jio_snprintf(buf, sizeof(buf), ":%d]", line_no); | |
139 out.print_raw_cr(buf); | |
140 } else { | |
141 // update 1-element cache for fast silent matches | |
142 last_file_name = file_name; | |
143 last_line_no = line_no; | |
144 } | |
145 return true; | |
146 } | |
147 | |
148 if (!is_error_reported()) { | |
149 // print a friendly hint: | |
150 fdStream out(defaultStream::output_fd()); | |
151 out.print_raw_cr("# To suppress the following error report, specify this argument"); | |
152 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); | |
153 out.print_raw (base_name); | |
154 char buf[16]; | |
155 jio_snprintf(buf, sizeof(buf), ":%d", line_no); | |
156 out.print_raw_cr(buf); | |
157 } | |
158 return false; | |
159 } | |
160 | |
161 #undef is_token_break | |
162 | |
163 #else | |
164 | |
165 // Place-holder for non-existent suppression check: | |
166 #define assert_is_suppressed(file_name, line_no) (false) | |
167 | |
168 #endif //PRODUCT | |
169 | |
170 void report_assertion_failure(const char* file_name, int line_no, const char* message) { | |
171 if (Debugging || assert_is_suppressed(file_name, line_no)) return; | |
172 VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); | |
173 err.report_and_die(); | |
174 } | |
175 | |
176 void report_fatal(const char* file_name, int line_no, const char* message) { | |
177 if (Debugging || assert_is_suppressed(file_name, line_no)) return; | |
178 VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); | |
179 err.report_and_die(); | |
180 } | |
181 | |
182 void report_fatal_vararg(const char* file_name, int line_no, const char* format, ...) { | |
183 char buffer[256]; | |
184 va_list ap; | |
185 va_start(ap, format); | |
186 jio_vsnprintf(buffer, sizeof(buffer), format, ap); | |
187 va_end(ap); | |
188 report_fatal(file_name, line_no, buffer); | |
189 } | |
190 | |
191 | |
192 // Used by report_vm_out_of_memory to detect recursion. | |
193 static jint _exiting_out_of_mem = 0; | |
194 | |
195 // Just passing the flow to VMError to handle error | |
196 void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message) { | |
197 if (Debugging || assert_is_suppressed(file_name, line_no)) return; | |
198 | |
199 // We try to gather additional information for the first out of memory | |
200 // error only; gathering additional data might cause an allocation and a | |
201 // recursive out_of_memory condition. | |
202 | |
203 const jint exiting = 1; | |
204 // If we succeed in changing the value, we're the first one in. | |
205 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; | |
206 | |
207 if (first_time_here) { | |
208 Thread* thread = ThreadLocalStorage::get_thread_slow(); | |
209 VMError(thread, size, message, file_name, line_no).report_and_die(); | |
210 } | |
227
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
211 |
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
212 // Dump core and abort |
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
213 vm_abort(true); |
0 | 214 } |
215 | |
216 void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) { | |
217 char buffer[256]; | |
218 va_list ap; | |
219 va_start(ap, format); | |
220 jio_vsnprintf(buffer, sizeof(buffer), format, ap); | |
221 va_end(ap); | |
222 report_vm_out_of_memory(file_name, line_no, size, buffer); | |
223 } | |
224 | |
225 void report_should_not_call(const char* file_name, int line_no) { | |
226 if (Debugging || assert_is_suppressed(file_name, line_no)) return; | |
227 VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotCall()", file_name, line_no); | |
228 err.report_and_die(); | |
229 } | |
230 | |
231 | |
232 void report_should_not_reach_here(const char* file_name, int line_no) { | |
233 if (Debugging || assert_is_suppressed(file_name, line_no)) return; | |
234 VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotReachHere()", file_name, line_no); | |
235 err.report_and_die(); | |
236 } | |
237 | |
238 | |
239 void report_unimplemented(const char* file_name, int line_no) { | |
240 if (Debugging || assert_is_suppressed(file_name, line_no)) return; | |
241 VMError err(ThreadLocalStorage::get_thread_slow(), "Unimplemented()", file_name, line_no); | |
242 err.report_and_die(); | |
243 } | |
244 | |
245 | |
246 void report_untested(const char* file_name, int line_no, const char* msg) { | |
247 #ifndef PRODUCT | |
248 warning("Untested: %s in %s: %d\n", msg, file_name, line_no); | |
249 #endif // PRODUCT | |
250 } | |
251 | |
252 void report_java_out_of_memory(const char* message) { | |
253 static jint out_of_memory_reported = 0; | |
254 | |
255 // A number of threads may attempt to report OutOfMemoryError at around the | |
256 // same time. To avoid dumping the heap or executing the data collection | |
257 // commands multiple times we just do it once when the first threads reports | |
258 // the error. | |
259 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { | |
260 // create heap dump before OnOutOfMemoryError commands are executed | |
261 if (HeapDumpOnOutOfMemoryError) { | |
262 tty->print_cr("java.lang.OutOfMemoryError: %s", message); | |
263 HeapDumper::dump_heap(); | |
264 } | |
265 | |
266 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { | |
267 VMError err(message); | |
268 err.report_java_out_of_memory(); | |
269 } | |
270 } | |
271 } | |
272 | |
273 | |
274 extern "C" void ps(); | |
275 | |
276 static bool error_reported = false; | |
277 | |
278 // call this when the VM is dying--it might loosen some asserts | |
279 void set_error_reported() { | |
280 error_reported = true; | |
281 } | |
282 | |
283 bool is_error_reported() { | |
284 return error_reported; | |
285 } | |
286 | |
287 // ------ helper functions for debugging go here ------------ | |
288 | |
289 #ifndef PRODUCT | |
290 // All debug entries should be wrapped with a stack allocated | |
291 // Command object. It makes sure a resource mark is set and | |
292 // flushes the logfile to prevent file sharing problems. | |
293 | |
294 class Command : public StackObj { | |
295 private: | |
296 ResourceMark rm; | |
297 ResetNoHandleMark rnhm; | |
298 HandleMark hm; | |
299 bool debug_save; | |
300 public: | |
301 static int level; | |
302 Command(const char* str) { | |
303 debug_save = Debugging; | |
304 Debugging = true; | |
305 if (level++ > 0) return; | |
306 tty->cr(); | |
307 tty->print_cr("\"Executing %s\"", str); | |
308 } | |
309 | |
310 ~Command() { tty->flush(); Debugging = debug_save; level--; } | |
311 }; | |
312 | |
313 int Command::level = 0; | |
314 | |
315 extern "C" void blob(CodeBlob* cb) { | |
316 Command c("blob"); | |
317 cb->print(); | |
318 } | |
319 | |
320 | |
321 extern "C" void dump_vtable(address p) { | |
322 Command c("dump_vtable"); | |
323 klassOop k = (klassOop)p; | |
324 instanceKlass::cast(k)->vtable()->print(); | |
325 } | |
326 | |
327 | |
328 extern "C" void nm(intptr_t p) { | |
329 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) | |
330 Command c("nm"); | |
331 CodeBlob* cb = CodeCache::find_blob((address)p); | |
332 if (cb == NULL) { | |
333 tty->print_cr("NULL"); | |
334 } else { | |
335 cb->print(); | |
336 } | |
337 } | |
338 | |
339 | |
340 extern "C" void disnm(intptr_t p) { | |
341 Command c("disnm"); | |
342 CodeBlob* cb = CodeCache::find_blob((address) p); | |
343 cb->print(); | |
344 Disassembler::decode(cb); | |
345 } | |
346 | |
347 | |
348 extern "C" void printnm(intptr_t p) { | |
349 char buffer[256]; | |
350 sprintf(buffer, "printnm: " INTPTR_FORMAT, p); | |
351 Command c(buffer); | |
352 CodeBlob* cb = CodeCache::find_blob((address) p); | |
353 if (cb->is_nmethod()) { | |
354 nmethod* nm = (nmethod*)cb; | |
355 nm->print_nmethod(true); | |
356 } | |
357 } | |
358 | |
359 | |
360 extern "C" void universe() { | |
361 Command c("universe"); | |
362 Universe::print(); | |
363 } | |
364 | |
365 | |
366 extern "C" void verify() { | |
367 // try to run a verify on the entire system | |
368 // note: this may not be safe if we're not at a safepoint; for debugging, | |
369 // this manipulates the safepoint settings to avoid assertion failures | |
370 Command c("universe verify"); | |
371 bool safe = SafepointSynchronize::is_at_safepoint(); | |
372 if (!safe) { | |
373 tty->print_cr("warning: not at safepoint -- verify may fail"); | |
374 SafepointSynchronize::set_is_at_safepoint(); | |
375 } | |
376 // Ensure Eden top is correct before verification | |
377 Universe::heap()->prepare_for_verify(); | |
378 Universe::verify(true); | |
379 if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); | |
380 } | |
381 | |
382 | |
383 extern "C" void pp(void* p) { | |
384 Command c("pp"); | |
385 FlagSetting fl(PrintVMMessages, true); | |
386 if (Universe::heap()->is_in(p)) { | |
387 oop obj = oop(p); | |
388 obj->print(); | |
389 } else { | |
390 tty->print("%#p", p); | |
391 } | |
392 } | |
393 | |
394 | |
395 // pv: print vm-printable object | |
396 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } | |
397 extern "C" void findpc(intptr_t x); | |
398 | |
399 extern "C" void ps() { // print stack | |
400 Command c("ps"); | |
401 | |
402 | |
403 // Prints the stack of the current Java thread | |
404 JavaThread* p = JavaThread::active(); | |
405 tty->print(" for thread: "); | |
406 p->print(); | |
407 tty->cr(); | |
408 | |
409 if (p->has_last_Java_frame()) { | |
410 // If the last_Java_fp is set we are in C land and | |
411 // can call the standard stack_trace function. | |
412 p->trace_stack(); | |
413 } else { | |
414 frame f = os::current_frame(); | |
415 RegisterMap reg_map(p); | |
416 f = f.sender(®_map); | |
417 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); | |
418 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); | |
419 pd_ps(f); | |
420 } | |
421 | |
422 } | |
423 | |
424 | |
425 extern "C" void psf() { // print stack frames | |
426 { | |
427 Command c("psf"); | |
428 JavaThread* p = JavaThread::active(); | |
429 tty->print(" for thread: "); | |
430 p->print(); | |
431 tty->cr(); | |
432 if (p->has_last_Java_frame()) { | |
433 p->trace_frames(); | |
434 } | |
435 } | |
436 } | |
437 | |
438 | |
439 extern "C" void threads() { | |
440 Command c("threads"); | |
441 Threads::print(false, true); | |
442 } | |
443 | |
444 | |
445 extern "C" void psd() { | |
446 Command c("psd"); | |
447 SystemDictionary::print(); | |
448 } | |
449 | |
450 | |
451 extern "C" void safepoints() { | |
452 Command c("safepoints"); | |
453 SafepointSynchronize::print_state(); | |
454 } | |
455 | |
456 | |
457 extern "C" void pss() { // print all stacks | |
458 Command c("pss"); | |
459 Threads::print(true, true); | |
460 } | |
461 | |
462 | |
463 extern "C" void debug() { // to set things up for compiler debugging | |
464 Command c("debug"); | |
465 WizardMode = true; | |
466 PrintVMMessages = PrintCompilation = true; | |
467 PrintInlining = PrintAssembly = true; | |
468 tty->flush(); | |
469 } | |
470 | |
471 | |
472 extern "C" void ndebug() { // undo debug() | |
473 Command c("ndebug"); | |
474 PrintCompilation = false; | |
475 PrintInlining = PrintAssembly = false; | |
476 tty->flush(); | |
477 } | |
478 | |
479 | |
480 extern "C" void flush() { | |
481 Command c("flush"); | |
482 tty->flush(); | |
483 } | |
484 | |
485 | |
486 extern "C" void events() { | |
487 Command c("events"); | |
488 Events::print_last(tty, 50); | |
489 } | |
490 | |
491 | |
492 extern "C" void nevents(int n) { | |
493 Command c("events"); | |
494 Events::print_last(tty, n); | |
495 } | |
496 | |
497 | |
498 // Given a heap address that was valid before the most recent GC, if | |
499 // the oop that used to contain it is still live, prints the new | |
500 // location of the oop and the address. Useful for tracking down | |
501 // certain kinds of naked oop and oop map bugs. | |
502 extern "C" void pnl(intptr_t old_heap_addr) { | |
503 // Print New Location of old heap address | |
504 Command c("pnl"); | |
505 #ifndef VALIDATE_MARK_SWEEP | |
506 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled"); | |
507 #else | |
508 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr); | |
509 #endif | |
510 } | |
511 | |
512 | |
513 extern "C" methodOop findm(intptr_t pc) { | |
514 Command c("findm"); | |
515 nmethod* nm = CodeCache::find_nmethod((address)pc); | |
516 return (nm == NULL) ? (methodOop)NULL : nm->method(); | |
517 } | |
518 | |
519 | |
520 extern "C" nmethod* findnm(intptr_t addr) { | |
521 Command c("findnm"); | |
522 return CodeCache::find_nmethod((address)addr); | |
523 } | |
524 | |
525 static address same_page(address x, address y) { | |
526 intptr_t page_bits = -os::vm_page_size(); | |
527 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) { | |
528 return x; | |
529 } else if (x > y) { | |
530 return (address)(intptr_t(y) | ~page_bits) + 1; | |
531 } else { | |
532 return (address)(intptr_t(y) & page_bits); | |
533 } | |
534 } | |
535 | |
536 | |
537 static void find(intptr_t x, bool print_pc) { | |
538 address addr = (address)x; | |
539 | |
540 CodeBlob* b = CodeCache::find_blob_unsafe(addr); | |
541 if (b != NULL) { | |
542 if (b->is_buffer_blob()) { | |
543 // the interpreter is generated into a buffer blob | |
544 InterpreterCodelet* i = Interpreter::codelet_containing(addr); | |
545 if (i != NULL) { | |
546 i->print(); | |
547 return; | |
548 } | |
549 if (Interpreter::contains(addr)) { | |
550 tty->print_cr(INTPTR_FORMAT " is pointing into interpreter code (not bytecode specific)", addr); | |
551 return; | |
552 } | |
553 // | |
554 if (AdapterHandlerLibrary::contains(b)) { | |
555 AdapterHandlerLibrary::print_handler(b); | |
556 } | |
557 // the stubroutines are generated into a buffer blob | |
558 StubCodeDesc* d = StubCodeDesc::desc_for(addr); | |
559 if (d != NULL) { | |
560 d->print(); | |
561 if (print_pc) tty->cr(); | |
562 return; | |
563 } | |
564 if (StubRoutines::contains(addr)) { | |
565 tty->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", addr); | |
566 return; | |
567 } | |
568 // the InlineCacheBuffer is using stubs generated into a buffer blob | |
569 if (InlineCacheBuffer::contains(addr)) { | |
432 | 570 tty->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer", addr); |
0 | 571 return; |
572 } | |
573 VtableStub* v = VtableStubs::stub_containing(addr); | |
574 if (v != NULL) { | |
575 v->print(); | |
576 return; | |
577 } | |
578 } | |
579 if (print_pc && b->is_nmethod()) { | |
580 ResourceMark rm; | |
581 tty->print("%#p: Compiled ", addr); | |
582 ((nmethod*)b)->method()->print_value_on(tty); | |
583 tty->print(" = (CodeBlob*)" INTPTR_FORMAT, b); | |
584 tty->cr(); | |
585 return; | |
586 } | |
587 if ( b->is_nmethod()) { | |
588 if (b->is_zombie()) { | |
589 tty->print_cr(INTPTR_FORMAT " is zombie nmethod", b); | |
590 } else if (b->is_not_entrant()) { | |
591 tty->print_cr(INTPTR_FORMAT " is non-entrant nmethod", b); | |
592 } | |
593 } | |
594 b->print(); | |
595 return; | |
596 } | |
597 | |
432 | 598 if (Universe::heap()->is_in(addr)) { |
0 | 599 HeapWord* p = Universe::heap()->block_start(addr); |
600 bool print = false; | |
601 // If we couldn't find it it just may mean that heap wasn't parseable | |
602 // See if we were just given an oop directly | |
603 if (p != NULL && Universe::heap()->block_is_obj(p)) { | |
604 print = true; | |
605 } else if (p == NULL && ((oopDesc*)addr)->is_oop()) { | |
606 p = (HeapWord*) addr; | |
607 print = true; | |
608 } | |
609 if (print) { | |
610 oop(p)->print(); | |
611 if (p != (HeapWord*)x && oop(p)->is_constMethod() && | |
612 constMethodOop(p)->contains(addr)) { | |
613 Thread *thread = Thread::current(); | |
614 HandleMark hm(thread); | |
615 methodHandle mh (thread, constMethodOop(p)->method()); | |
616 if (!mh->is_native()) { | |
617 tty->print_cr("bci_from(%p) = %d; print_codes():", | |
618 addr, mh->bci_from(address(x))); | |
619 mh->print_codes(); | |
620 } | |
621 } | |
622 return; | |
623 } | |
432 | 624 } else if (Universe::heap()->is_in_reserved(addr)) { |
625 tty->print_cr(INTPTR_FORMAT " is an unallocated location in the heap", addr); | |
626 return; | |
0 | 627 } |
432 | 628 |
0 | 629 if (JNIHandles::is_global_handle((jobject) addr)) { |
432 | 630 tty->print_cr(INTPTR_FORMAT " is a global jni handle", addr); |
0 | 631 return; |
632 } | |
633 if (JNIHandles::is_weak_global_handle((jobject) addr)) { | |
432 | 634 tty->print_cr(INTPTR_FORMAT " is a weak global jni handle", addr); |
0 | 635 return; |
636 } | |
637 if (JNIHandleBlock::any_contains((jobject) addr)) { | |
432 | 638 tty->print_cr(INTPTR_FORMAT " is a local jni handle", addr); |
0 | 639 return; |
640 } | |
641 | |
642 for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { | |
432 | 643 // Check for privilege stack |
0 | 644 if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) { |
432 | 645 tty->print_cr(INTPTR_FORMAT " is pointing into the privilege stack for thread: " INTPTR_FORMAT, addr, thread); |
0 | 646 return; |
647 } | |
648 // If the addr is a java thread print information about that. | |
649 if (addr == (address)thread) { | |
650 thread->print(); | |
651 return; | |
652 } | |
653 } | |
654 | |
655 // Try an OS specific find | |
656 if (os::find(addr)) { | |
657 return; | |
658 } | |
659 | |
660 if (print_pc) { | |
661 tty->print_cr(INTPTR_FORMAT ": probably in C++ code; check debugger", addr); | |
662 Disassembler::decode(same_page(addr-40,addr),same_page(addr+40,addr)); | |
663 return; | |
664 } | |
665 | |
432 | 666 tty->print_cr(INTPTR_FORMAT " is pointing to unknown location", addr); |
0 | 667 } |
668 | |
669 | |
670 class LookForRefInGenClosure : public OopsInGenClosure { | |
671 public: | |
672 oop target; | |
673 void do_oop(oop* o) { | |
674 if (o != NULL && *o == target) { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
675 tty->print_cr(INTPTR_FORMAT, o); |
0 | 676 } |
677 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
678 void do_oop(narrowOop* o) { ShouldNotReachHere(); } |
0 | 679 }; |
680 | |
681 | |
682 class LookForRefInObjectClosure : public ObjectClosure { | |
683 private: | |
684 LookForRefInGenClosure look_in_object; | |
685 public: | |
686 LookForRefInObjectClosure(oop target) { look_in_object.target = target; } | |
687 void do_object(oop obj) { | |
688 obj->oop_iterate(&look_in_object); | |
689 } | |
690 }; | |
691 | |
692 | |
693 static void findref(intptr_t x) { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
694 CollectedHeap *ch = Universe::heap(); |
0 | 695 LookForRefInGenClosure lookFor; |
696 lookFor.target = (oop) x; | |
697 LookForRefInObjectClosure look_in_object((oop) x); | |
698 | |
699 tty->print_cr("Searching heap:"); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
700 ch->object_iterate(&look_in_object); |
0 | 701 |
702 tty->print_cr("Searching strong roots:"); | |
703 Universe::oops_do(&lookFor, false); | |
704 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles | |
705 Threads::oops_do(&lookFor); | |
706 ObjectSynchronizer::oops_do(&lookFor); | |
707 //FlatProfiler::oops_do(&lookFor); | |
708 SystemDictionary::oops_do(&lookFor); | |
709 | |
710 tty->print_cr("Done."); | |
711 } | |
712 | |
713 class FindClassObjectClosure: public ObjectClosure { | |
714 private: | |
715 const char* _target; | |
716 public: | |
717 FindClassObjectClosure(const char name[]) { _target = name; } | |
718 | |
719 virtual void do_object(oop obj) { | |
720 if (obj->is_klass()) { | |
721 Klass* k = klassOop(obj)->klass_part(); | |
722 if (k->name() != NULL) { | |
723 ResourceMark rm; | |
724 const char* ext = k->external_name(); | |
725 if ( strcmp(_target, ext) == 0 ) { | |
726 tty->print_cr("Found " INTPTR_FORMAT, obj); | |
727 obj->print(); | |
728 } | |
729 } | |
730 } | |
731 } | |
732 }; | |
733 | |
734 // | |
735 extern "C" void findclass(const char name[]) { | |
736 Command c("findclass"); | |
737 if (name != NULL) { | |
738 tty->print_cr("Finding class %s -> ", name); | |
739 FindClassObjectClosure srch(name); | |
740 Universe::heap()->permanent_object_iterate(&srch); | |
741 } | |
742 } | |
743 | |
744 // Another interface that isn't ambiguous in dbx. | |
745 // Can we someday rename the other find to hsfind? | |
746 extern "C" void hsfind(intptr_t x) { | |
747 Command c("hsfind"); | |
748 find(x, false); | |
749 } | |
750 | |
751 | |
752 extern "C" void hsfindref(intptr_t x) { | |
753 Command c("hsfindref"); | |
754 findref(x); | |
755 } | |
756 | |
757 extern "C" void find(intptr_t x) { | |
758 Command c("find"); | |
759 find(x, false); | |
760 } | |
761 | |
762 | |
763 extern "C" void findpc(intptr_t x) { | |
764 Command c("findpc"); | |
765 find(x, true); | |
766 } | |
767 | |
768 | |
769 // int versions of all methods to avoid having to type type casts in the debugger | |
770 | |
771 void pp(intptr_t p) { pp((void*)p); } | |
772 void pp(oop p) { pp((void*)p); } | |
773 | |
774 void help() { | |
775 Command c("help"); | |
776 tty->print_cr("basic"); | |
777 tty->print_cr(" pp(void* p) - try to make sense of p"); | |
778 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); | |
779 tty->print_cr(" ps() - print current thread stack"); | |
780 tty->print_cr(" pss() - print all thread stacks"); | |
781 tty->print_cr(" pm(int pc) - print methodOop given compiled PC"); | |
782 tty->print_cr(" findm(intptr_t pc) - finds methodOop"); | |
783 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); | |
784 | |
785 tty->print_cr("misc."); | |
786 tty->print_cr(" flush() - flushes the log file"); | |
787 tty->print_cr(" events() - dump last 50 events"); | |
788 | |
789 | |
790 tty->print_cr("compiler debugging"); | |
791 tty->print_cr(" debug() - to set things up for compiler debugging"); | |
792 tty->print_cr(" ndebug() - undo debug"); | |
793 } | |
794 | |
795 #if 0 | |
796 | |
797 // BobV's command parser for debugging on windows when nothing else works. | |
798 | |
799 enum CommandID { | |
800 CMDID_HELP, | |
801 CMDID_QUIT, | |
802 CMDID_HSFIND, | |
803 CMDID_PSS, | |
804 CMDID_PS, | |
805 CMDID_PSF, | |
806 CMDID_FINDM, | |
807 CMDID_FINDNM, | |
808 CMDID_PP, | |
809 CMDID_BPT, | |
810 CMDID_EXIT, | |
811 CMDID_VERIFY, | |
812 CMDID_THREADS, | |
813 CMDID_ILLEGAL = 99 | |
814 }; | |
815 | |
816 struct CommandParser { | |
817 char *name; | |
818 CommandID code; | |
819 char *description; | |
820 }; | |
821 | |
822 struct CommandParser CommandList[] = { | |
823 (char *)"help", CMDID_HELP, " Dump this list", | |
824 (char *)"quit", CMDID_QUIT, " Return from this routine", | |
825 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", | |
826 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", | |
827 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", | |
828 (char *)"psf", CMDID_PSF, " Print All Stack Frames", | |
829 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC", | |
830 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", | |
831 (char *)"pp", CMDID_PP, " Find out something about a pointer", | |
832 (char *)"break", CMDID_BPT, " Execute a breakpoint", | |
833 (char *)"exitvm", CMDID_EXIT, "Exit the VM", | |
834 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", | |
835 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", | |
836 (char *)0, CMDID_ILLEGAL | |
837 }; | |
838 | |
839 | |
840 // get_debug_command() | |
841 // | |
842 // Read a command from standard input. | |
843 // This is useful when you have a debugger | |
844 // which doesn't support calling into functions. | |
845 // | |
846 void get_debug_command() | |
847 { | |
848 ssize_t count; | |
849 int i,j; | |
850 bool gotcommand; | |
851 intptr_t addr; | |
852 char buffer[256]; | |
853 nmethod *nm; | |
854 methodOop m; | |
855 | |
856 tty->print_cr("You have entered the diagnostic command interpreter"); | |
857 tty->print("The supported commands are:\n"); | |
858 for ( i=0; ; i++ ) { | |
859 if ( CommandList[i].code == CMDID_ILLEGAL ) | |
860 break; | |
861 tty->print_cr(" %s \n", CommandList[i].name ); | |
862 } | |
863 | |
864 while ( 1 ) { | |
865 gotcommand = false; | |
866 tty->print("Please enter a command: "); | |
867 count = scanf("%s", buffer) ; | |
868 if ( count >=0 ) { | |
869 for ( i=0; ; i++ ) { | |
870 if ( CommandList[i].code == CMDID_ILLEGAL ) { | |
871 if (!gotcommand) tty->print("Invalid command, please try again\n"); | |
872 break; | |
873 } | |
874 if ( strcmp(buffer, CommandList[i].name) == 0 ) { | |
875 gotcommand = true; | |
876 switch ( CommandList[i].code ) { | |
877 case CMDID_PS: | |
878 ps(); | |
879 break; | |
880 case CMDID_PSS: | |
881 pss(); | |
882 break; | |
883 case CMDID_PSF: | |
884 psf(); | |
885 break; | |
886 case CMDID_FINDM: | |
887 tty->print("Please enter the hex addr to pass to findm: "); | |
888 scanf("%I64X", &addr); | |
889 m = (methodOop)findm(addr); | |
890 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); | |
891 break; | |
892 case CMDID_FINDNM: | |
893 tty->print("Please enter the hex addr to pass to findnm: "); | |
894 scanf("%I64X", &addr); | |
895 nm = (nmethod*)findnm(addr); | |
896 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); | |
897 break; | |
898 case CMDID_PP: | |
899 tty->print("Please enter the hex addr to pass to pp: "); | |
900 scanf("%I64X", &addr); | |
901 pp((void*)addr); | |
902 break; | |
903 case CMDID_EXIT: | |
904 exit(0); | |
905 case CMDID_HELP: | |
906 tty->print("Here are the supported commands: "); | |
907 for ( j=0; ; j++ ) { | |
908 if ( CommandList[j].code == CMDID_ILLEGAL ) | |
909 break; | |
910 tty->print_cr(" %s -- %s\n", CommandList[j].name, | |
911 CommandList[j].description ); | |
912 } | |
913 break; | |
914 case CMDID_QUIT: | |
915 return; | |
916 break; | |
917 case CMDID_BPT: | |
918 BREAKPOINT; | |
919 break; | |
920 case CMDID_VERIFY: | |
921 verify();; | |
922 break; | |
923 case CMDID_THREADS: | |
924 threads();; | |
925 break; | |
926 case CMDID_HSFIND: | |
927 tty->print("Please enter the hex addr to pass to hsfind: "); | |
928 scanf("%I64X", &addr); | |
929 tty->print("Calling hsfind(0x%I64X)\n", addr); | |
930 hsfind(addr); | |
931 break; | |
932 default: | |
933 case CMDID_ILLEGAL: | |
934 break; | |
935 } | |
936 } | |
937 } | |
938 } | |
939 } | |
940 } | |
941 #endif | |
942 | |
943 #endif // PRODUCT |