Mercurial > hg > graal-compiler
annotate src/share/vm/utilities/debug.cpp @ 1091:6aa7255741f3
6906727: UseCompressedOops: some card-marking fixes related to object arrays
Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17).
Reviewed-by: kvn, coleenp, jmasa
author | ysr |
---|---|
date | Thu, 03 Dec 2009 15:01:57 -0800 |
parents | 148e5441d916 |
children | f03d0a26bf83 |
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 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
705 Threads::oops_do(&lookFor, NULL); |
0 | 706 ObjectSynchronizer::oops_do(&lookFor); |
707 //FlatProfiler::oops_do(&lookFor); | |
708 SystemDictionary::oops_do(&lookFor); | |
709 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
710 tty->print_cr("Searching code cache:"); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
711 CodeCache::oops_do(&lookFor); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
432
diff
changeset
|
712 |
0 | 713 tty->print_cr("Done."); |
714 } | |
715 | |
716 class FindClassObjectClosure: public ObjectClosure { | |
717 private: | |
718 const char* _target; | |
719 public: | |
720 FindClassObjectClosure(const char name[]) { _target = name; } | |
721 | |
722 virtual void do_object(oop obj) { | |
723 if (obj->is_klass()) { | |
724 Klass* k = klassOop(obj)->klass_part(); | |
725 if (k->name() != NULL) { | |
726 ResourceMark rm; | |
727 const char* ext = k->external_name(); | |
728 if ( strcmp(_target, ext) == 0 ) { | |
729 tty->print_cr("Found " INTPTR_FORMAT, obj); | |
730 obj->print(); | |
731 } | |
732 } | |
733 } | |
734 } | |
735 }; | |
736 | |
737 // | |
738 extern "C" void findclass(const char name[]) { | |
739 Command c("findclass"); | |
740 if (name != NULL) { | |
741 tty->print_cr("Finding class %s -> ", name); | |
742 FindClassObjectClosure srch(name); | |
743 Universe::heap()->permanent_object_iterate(&srch); | |
744 } | |
745 } | |
746 | |
747 // Another interface that isn't ambiguous in dbx. | |
748 // Can we someday rename the other find to hsfind? | |
749 extern "C" void hsfind(intptr_t x) { | |
750 Command c("hsfind"); | |
751 find(x, false); | |
752 } | |
753 | |
754 | |
755 extern "C" void hsfindref(intptr_t x) { | |
756 Command c("hsfindref"); | |
757 findref(x); | |
758 } | |
759 | |
760 extern "C" void find(intptr_t x) { | |
761 Command c("find"); | |
762 find(x, false); | |
763 } | |
764 | |
765 | |
766 extern "C" void findpc(intptr_t x) { | |
767 Command c("findpc"); | |
768 find(x, true); | |
769 } | |
770 | |
771 | |
772 // int versions of all methods to avoid having to type type casts in the debugger | |
773 | |
774 void pp(intptr_t p) { pp((void*)p); } | |
775 void pp(oop p) { pp((void*)p); } | |
776 | |
777 void help() { | |
778 Command c("help"); | |
779 tty->print_cr("basic"); | |
780 tty->print_cr(" pp(void* p) - try to make sense of p"); | |
781 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); | |
782 tty->print_cr(" ps() - print current thread stack"); | |
783 tty->print_cr(" pss() - print all thread stacks"); | |
784 tty->print_cr(" pm(int pc) - print methodOop given compiled PC"); | |
785 tty->print_cr(" findm(intptr_t pc) - finds methodOop"); | |
786 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); | |
787 | |
788 tty->print_cr("misc."); | |
789 tty->print_cr(" flush() - flushes the log file"); | |
790 tty->print_cr(" events() - dump last 50 events"); | |
791 | |
792 | |
793 tty->print_cr("compiler debugging"); | |
794 tty->print_cr(" debug() - to set things up for compiler debugging"); | |
795 tty->print_cr(" ndebug() - undo debug"); | |
796 } | |
797 | |
798 #if 0 | |
799 | |
800 // BobV's command parser for debugging on windows when nothing else works. | |
801 | |
802 enum CommandID { | |
803 CMDID_HELP, | |
804 CMDID_QUIT, | |
805 CMDID_HSFIND, | |
806 CMDID_PSS, | |
807 CMDID_PS, | |
808 CMDID_PSF, | |
809 CMDID_FINDM, | |
810 CMDID_FINDNM, | |
811 CMDID_PP, | |
812 CMDID_BPT, | |
813 CMDID_EXIT, | |
814 CMDID_VERIFY, | |
815 CMDID_THREADS, | |
816 CMDID_ILLEGAL = 99 | |
817 }; | |
818 | |
819 struct CommandParser { | |
820 char *name; | |
821 CommandID code; | |
822 char *description; | |
823 }; | |
824 | |
825 struct CommandParser CommandList[] = { | |
826 (char *)"help", CMDID_HELP, " Dump this list", | |
827 (char *)"quit", CMDID_QUIT, " Return from this routine", | |
828 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", | |
829 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", | |
830 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", | |
831 (char *)"psf", CMDID_PSF, " Print All Stack Frames", | |
832 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC", | |
833 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", | |
834 (char *)"pp", CMDID_PP, " Find out something about a pointer", | |
835 (char *)"break", CMDID_BPT, " Execute a breakpoint", | |
836 (char *)"exitvm", CMDID_EXIT, "Exit the VM", | |
837 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", | |
838 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", | |
839 (char *)0, CMDID_ILLEGAL | |
840 }; | |
841 | |
842 | |
843 // get_debug_command() | |
844 // | |
845 // Read a command from standard input. | |
846 // This is useful when you have a debugger | |
847 // which doesn't support calling into functions. | |
848 // | |
849 void get_debug_command() | |
850 { | |
851 ssize_t count; | |
852 int i,j; | |
853 bool gotcommand; | |
854 intptr_t addr; | |
855 char buffer[256]; | |
856 nmethod *nm; | |
857 methodOop m; | |
858 | |
859 tty->print_cr("You have entered the diagnostic command interpreter"); | |
860 tty->print("The supported commands are:\n"); | |
861 for ( i=0; ; i++ ) { | |
862 if ( CommandList[i].code == CMDID_ILLEGAL ) | |
863 break; | |
864 tty->print_cr(" %s \n", CommandList[i].name ); | |
865 } | |
866 | |
867 while ( 1 ) { | |
868 gotcommand = false; | |
869 tty->print("Please enter a command: "); | |
870 count = scanf("%s", buffer) ; | |
871 if ( count >=0 ) { | |
872 for ( i=0; ; i++ ) { | |
873 if ( CommandList[i].code == CMDID_ILLEGAL ) { | |
874 if (!gotcommand) tty->print("Invalid command, please try again\n"); | |
875 break; | |
876 } | |
877 if ( strcmp(buffer, CommandList[i].name) == 0 ) { | |
878 gotcommand = true; | |
879 switch ( CommandList[i].code ) { | |
880 case CMDID_PS: | |
881 ps(); | |
882 break; | |
883 case CMDID_PSS: | |
884 pss(); | |
885 break; | |
886 case CMDID_PSF: | |
887 psf(); | |
888 break; | |
889 case CMDID_FINDM: | |
890 tty->print("Please enter the hex addr to pass to findm: "); | |
891 scanf("%I64X", &addr); | |
892 m = (methodOop)findm(addr); | |
893 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); | |
894 break; | |
895 case CMDID_FINDNM: | |
896 tty->print("Please enter the hex addr to pass to findnm: "); | |
897 scanf("%I64X", &addr); | |
898 nm = (nmethod*)findnm(addr); | |
899 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); | |
900 break; | |
901 case CMDID_PP: | |
902 tty->print("Please enter the hex addr to pass to pp: "); | |
903 scanf("%I64X", &addr); | |
904 pp((void*)addr); | |
905 break; | |
906 case CMDID_EXIT: | |
907 exit(0); | |
908 case CMDID_HELP: | |
909 tty->print("Here are the supported commands: "); | |
910 for ( j=0; ; j++ ) { | |
911 if ( CommandList[j].code == CMDID_ILLEGAL ) | |
912 break; | |
913 tty->print_cr(" %s -- %s\n", CommandList[j].name, | |
914 CommandList[j].description ); | |
915 } | |
916 break; | |
917 case CMDID_QUIT: | |
918 return; | |
919 break; | |
920 case CMDID_BPT: | |
921 BREAKPOINT; | |
922 break; | |
923 case CMDID_VERIFY: | |
924 verify();; | |
925 break; | |
926 case CMDID_THREADS: | |
927 threads();; | |
928 break; | |
929 case CMDID_HSFIND: | |
930 tty->print("Please enter the hex addr to pass to hsfind: "); | |
931 scanf("%I64X", &addr); | |
932 tty->print("Calling hsfind(0x%I64X)\n", addr); | |
933 hsfind(addr); | |
934 break; | |
935 default: | |
936 case CMDID_ILLEGAL: | |
937 break; | |
938 } | |
939 } | |
940 } | |
941 } | |
942 } | |
943 } | |
944 #endif | |
945 | |
946 #endif // PRODUCT |