src/share/vm/utilities/debug.cpp

Mon, 03 Jan 2011 14:09:11 -0500

author
coleenp
date
Mon, 03 Jan 2011 14:09:11 -0500
changeset 2418
36c186bcc085
parent 2350
2f644f85485d
child 2497
3582bf76420e
permissions
-rw-r--r--

6302804: Hotspot VM dies ungraceful death when C heap is exhausted in various places.
Summary: enhance the error reporting mechanism to help user to fix the problem rather than making it look like a VM error.
Reviewed-by: kvn, kamg

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

mercurial