src/share/vm/utilities/debug.cpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 867
275a3b7ff0d6
child 1424
148e5441d916
permissions
-rw-r--r--

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

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

mercurial