src/share/vm/utilities/debug.cpp

Fri, 10 Jun 2011 15:08:36 -0700

author
minqi
date
Fri, 10 Jun 2011 15:08:36 -0700
changeset 2964
2a241e764894
parent 2868
2e038ad0c1d0
child 3156
f08d439fab8c
permissions
-rw-r--r--

6941923: RFE: Handling large log files produced by long running Java Applications
Summary: supply optinal flags to realize gc log rotation
Reviewed-by: ysr, jwilhelm

     1 /*
     2  * Copyright (c) 1997, 2011, 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_out_of_shared_space(SharedSpaceType shared_space) {
   267   static const char* name[] = {
   268     "permanent generation",
   269     "shared read only space",
   270     "shared read write space",
   271     "shared miscellaneous data space"
   272   };
   273   static const char* flag[] = {
   274     "PermGen",
   275     "SharedReadOnlySize",
   276     "SharedReadWriteSize",
   277     "SharedMiscDataSize"
   278   };
   280    warning("\nThe %s is not large enough\n"
   281            "to preload requested classes. Use -XX:%s=\n"
   282            "to increase the initial size of %s.\n",
   283            name[shared_space], flag[shared_space], name[shared_space]);
   284    exit(2);
   285 }
   287 void report_java_out_of_memory(const char* message) {
   288   static jint out_of_memory_reported = 0;
   290   // A number of threads may attempt to report OutOfMemoryError at around the
   291   // same time. To avoid dumping the heap or executing the data collection
   292   // commands multiple times we just do it once when the first threads reports
   293   // the error.
   294   if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
   295     // create heap dump before OnOutOfMemoryError commands are executed
   296     if (HeapDumpOnOutOfMemoryError) {
   297       tty->print_cr("java.lang.OutOfMemoryError: %s", message);
   298       HeapDumper::dump_heap_from_oome();
   299     }
   301     if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
   302       VMError err(message);
   303       err.report_java_out_of_memory();
   304     }
   305   }
   306 }
   309 extern "C" void ps();
   311 static bool error_reported = false;
   313 // call this when the VM is dying--it might loosen some asserts
   314 void set_error_reported() {
   315   error_reported = true;
   316 }
   318 bool is_error_reported() {
   319     return error_reported;
   320 }
   322 #ifndef PRODUCT
   323 #include <signal.h>
   325 void test_error_handler(size_t test_num)
   326 {
   327   if (test_num == 0) return;
   329   // If asserts are disabled, use the corresponding guarantee instead.
   330   size_t n = test_num;
   331   NOT_DEBUG(if (n <= 2) n += 2);
   333   const char* const str = "hello";
   334   const size_t      num = (size_t)os::vm_page_size();
   336   const char* const eol = os::line_separator();
   337   const char* const msg = "this message should be truncated during formatting";
   339   // Keep this in sync with test/runtime/6888954/vmerrors.sh.
   340   switch (n) {
   341     case  1: assert(str == NULL, "expected null");
   342     case  2: assert(num == 1023 && *str == 'X',
   343                     err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
   344     case  3: guarantee(str == NULL, "expected null");
   345     case  4: guarantee(num == 1023 && *str == 'X',
   346                        err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
   347     case  5: fatal("expected null");
   348     case  6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
   349     case  7: fatal(err_msg("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
   350                            "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
   351                            "%s%s#    %s%s#    %s%s#    %s%s#    %s",
   352                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
   353                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
   354                            msg, eol, msg, eol, msg, eol, msg, eol, msg));
   355     case  8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
   356     case  9: ShouldNotCallThis();
   357     case 10: ShouldNotReachHere();
   358     case 11: Unimplemented();
   359     // This is last because it does not generate an hs_err* file on Windows.
   360     case 12: os::signal_raise(SIGSEGV);
   362     default: ShouldNotReachHere();
   363   }
   364 }
   365 #endif // #ifndef PRODUCT
   367 // ------ helper functions for debugging go here ------------
   369 #ifndef PRODUCT
   370 // All debug entries should be wrapped with a stack allocated
   371 // Command object. It makes sure a resource mark is set and
   372 // flushes the logfile to prevent file sharing problems.
   374 class Command : public StackObj {
   375  private:
   376   ResourceMark rm;
   377   ResetNoHandleMark rnhm;
   378   HandleMark   hm;
   379   bool debug_save;
   380  public:
   381   static int level;
   382   Command(const char* str) {
   383     debug_save = Debugging;
   384     Debugging = true;
   385     if (level++ > 0)  return;
   386     tty->cr();
   387     tty->print_cr("\"Executing %s\"", str);
   388   }
   390   ~Command() { tty->flush(); Debugging = debug_save; level--; }
   391 };
   393 int Command::level = 0;
   395 extern "C" void blob(CodeBlob* cb) {
   396   Command c("blob");
   397   cb->print();
   398 }
   401 extern "C" void dump_vtable(address p) {
   402   Command c("dump_vtable");
   403   klassOop k = (klassOop)p;
   404   instanceKlass::cast(k)->vtable()->print();
   405 }
   408 extern "C" void nm(intptr_t p) {
   409   // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
   410   Command c("nm");
   411   CodeBlob* cb = CodeCache::find_blob((address)p);
   412   if (cb == NULL) {
   413     tty->print_cr("NULL");
   414   } else {
   415     cb->print();
   416   }
   417 }
   420 extern "C" void disnm(intptr_t p) {
   421   Command c("disnm");
   422   CodeBlob* cb = CodeCache::find_blob((address) p);
   423   nmethod* nm = cb->as_nmethod_or_null();
   424   if (nm) {
   425     nm->print();
   426     Disassembler::decode(nm);
   427   } else {
   428     cb->print();
   429     Disassembler::decode(cb);
   430   }
   431 }
   434 extern "C" void printnm(intptr_t p) {
   435   char buffer[256];
   436   sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
   437   Command c(buffer);
   438   CodeBlob* cb = CodeCache::find_blob((address) p);
   439   if (cb->is_nmethod()) {
   440     nmethod* nm = (nmethod*)cb;
   441     nm->print_nmethod(true);
   442   }
   443 }
   446 extern "C" void universe() {
   447   Command c("universe");
   448   Universe::print();
   449 }
   452 extern "C" void verify() {
   453   // try to run a verify on the entire system
   454   // note: this may not be safe if we're not at a safepoint; for debugging,
   455   // this manipulates the safepoint settings to avoid assertion failures
   456   Command c("universe verify");
   457   bool safe = SafepointSynchronize::is_at_safepoint();
   458   if (!safe) {
   459     tty->print_cr("warning: not at safepoint -- verify may fail");
   460     SafepointSynchronize::set_is_at_safepoint();
   461   }
   462   // Ensure Eden top is correct before verification
   463   Universe::heap()->prepare_for_verify();
   464   Universe::verify(true);
   465   if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
   466 }
   469 extern "C" void pp(void* p) {
   470   Command c("pp");
   471   FlagSetting fl(PrintVMMessages, true);
   472   FlagSetting f2(DisplayVMOutput, true);
   473   if (Universe::heap()->is_in(p)) {
   474     oop obj = oop(p);
   475     obj->print();
   476   } else {
   477     tty->print("%#p", p);
   478   }
   479 }
   482 // pv: print vm-printable object
   483 extern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
   484 extern "C" void findpc(intptr_t x);
   486 extern "C" void ps() { // print stack
   487   Command c("ps");
   490   // Prints the stack of the current Java thread
   491   JavaThread* p = JavaThread::active();
   492   tty->print(" for thread: ");
   493   p->print();
   494   tty->cr();
   496   if (p->has_last_Java_frame()) {
   497     // If the last_Java_fp is set we are in C land and
   498     // can call the standard stack_trace function.
   499     p->trace_stack();
   500   } else {
   501     frame f = os::current_frame();
   502     RegisterMap reg_map(p);
   503     f = f.sender(&reg_map);
   504     tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
   505     p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
   506   pd_ps(f);
   507   }
   509 }
   511 extern "C" void pfl() {
   512   // print frame layout
   513   Command c("pfl");
   514   JavaThread* p = JavaThread::active();
   515   tty->print(" for thread: ");
   516   p->print();
   517   tty->cr();
   518   if (p->has_last_Java_frame()) {
   519     p->print_frame_layout();
   520   }
   521 }
   523 extern "C" void psf() { // print stack frames
   524   {
   525     Command c("psf");
   526     JavaThread* p = JavaThread::active();
   527     tty->print(" for thread: ");
   528     p->print();
   529     tty->cr();
   530     if (p->has_last_Java_frame()) {
   531       p->trace_frames();
   532     }
   533   }
   534 }
   537 extern "C" void threads() {
   538   Command c("threads");
   539   Threads::print(false, true);
   540 }
   543 extern "C" void psd() {
   544   Command c("psd");
   545   SystemDictionary::print();
   546 }
   549 extern "C" void safepoints() {
   550   Command c("safepoints");
   551   SafepointSynchronize::print_state();
   552 }
   555 extern "C" void pss() { // print all stacks
   556   Command c("pss");
   557   Threads::print(true, true);
   558 }
   561 extern "C" void debug() {               // to set things up for compiler debugging
   562   Command c("debug");
   563   WizardMode = true;
   564   PrintVMMessages = PrintCompilation = true;
   565   PrintInlining = PrintAssembly = true;
   566   tty->flush();
   567 }
   570 extern "C" void ndebug() {              // undo debug()
   571   Command c("ndebug");
   572   PrintCompilation = false;
   573   PrintInlining = PrintAssembly = false;
   574   tty->flush();
   575 }
   578 extern "C" void flush()  {
   579   Command c("flush");
   580   tty->flush();
   581 }
   584 extern "C" void events() {
   585   Command c("events");
   586   Events::print_last(tty, 50);
   587 }
   590 extern "C" void nevents(int n) {
   591   Command c("events");
   592   Events::print_last(tty, n);
   593 }
   596 // Given a heap address that was valid before the most recent GC, if
   597 // the oop that used to contain it is still live, prints the new
   598 // location of the oop and the address. Useful for tracking down
   599 // certain kinds of naked oop and oop map bugs.
   600 extern "C" void pnl(intptr_t old_heap_addr) {
   601   // Print New Location of old heap address
   602   Command c("pnl");
   603 #ifndef VALIDATE_MARK_SWEEP
   604   tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
   605 #else
   606   MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
   607 #endif
   608 }
   611 extern "C" methodOop findm(intptr_t pc) {
   612   Command c("findm");
   613   nmethod* nm = CodeCache::find_nmethod((address)pc);
   614   return (nm == NULL) ? (methodOop)NULL : nm->method();
   615 }
   618 extern "C" nmethod* findnm(intptr_t addr) {
   619   Command c("findnm");
   620   return  CodeCache::find_nmethod((address)addr);
   621 }
   623 static address same_page(address x, address y) {
   624   intptr_t page_bits = -os::vm_page_size();
   625   if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
   626     return x;
   627   } else if (x > y) {
   628     return (address)(intptr_t(y) | ~page_bits) + 1;
   629   } else {
   630     return (address)(intptr_t(y) & page_bits);
   631   }
   632 }
   634 class LookForRefInGenClosure : public OopsInGenClosure {
   635 public:
   636   oop target;
   637   void do_oop(oop* o) {
   638     if (o != NULL && *o == target) {
   639       tty->print_cr(INTPTR_FORMAT, o);
   640     }
   641   }
   642   void do_oop(narrowOop* o) { ShouldNotReachHere(); }
   643 };
   646 class LookForRefInObjectClosure : public ObjectClosure {
   647 private:
   648   LookForRefInGenClosure look_in_object;
   649 public:
   650   LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
   651   void do_object(oop obj) {
   652     obj->oop_iterate(&look_in_object);
   653   }
   654 };
   657 static void findref(intptr_t x) {
   658   CollectedHeap *ch = Universe::heap();
   659   LookForRefInGenClosure lookFor;
   660   lookFor.target = (oop) x;
   661   LookForRefInObjectClosure look_in_object((oop) x);
   663   tty->print_cr("Searching heap:");
   664   ch->object_iterate(&look_in_object);
   666   tty->print_cr("Searching strong roots:");
   667   Universe::oops_do(&lookFor, false);
   668   JNIHandles::oops_do(&lookFor);   // Global (strong) JNI handles
   669   Threads::oops_do(&lookFor, NULL);
   670   ObjectSynchronizer::oops_do(&lookFor);
   671   //FlatProfiler::oops_do(&lookFor);
   672   SystemDictionary::oops_do(&lookFor);
   674   tty->print_cr("Searching code cache:");
   675   CodeCache::oops_do(&lookFor);
   677   tty->print_cr("Done.");
   678 }
   680 class FindClassObjectClosure: public ObjectClosure {
   681   private:
   682     const char* _target;
   683   public:
   684     FindClassObjectClosure(const char name[])  { _target = name; }
   686     virtual void do_object(oop obj) {
   687       if (obj->is_klass()) {
   688         Klass* k = klassOop(obj)->klass_part();
   689         if (k->name() != NULL) {
   690           ResourceMark rm;
   691           const char* ext = k->external_name();
   692           if ( strcmp(_target, ext) == 0 ) {
   693             tty->print_cr("Found " INTPTR_FORMAT, obj);
   694             obj->print();
   695           }
   696         }
   697       }
   698     }
   699 };
   701 //
   702 extern "C" void findclass(const char name[]) {
   703   Command c("findclass");
   704   if (name != NULL) {
   705     tty->print_cr("Finding class %s -> ", name);
   706     FindClassObjectClosure srch(name);
   707     Universe::heap()->permanent_object_iterate(&srch);
   708   }
   709 }
   711 // Another interface that isn't ambiguous in dbx.
   712 // Can we someday rename the other find to hsfind?
   713 extern "C" void hsfind(intptr_t x) {
   714   Command c("hsfind");
   715   os::print_location(tty, x, false);
   716 }
   719 extern "C" void hsfindref(intptr_t x) {
   720   Command c("hsfindref");
   721   findref(x);
   722 }
   724 extern "C" void find(intptr_t x) {
   725   Command c("find");
   726   os::print_location(tty, x, false);
   727 }
   730 extern "C" void findpc(intptr_t x) {
   731   Command c("findpc");
   732   os::print_location(tty, x, true);
   733 }
   736 // int versions of all methods to avoid having to type type casts in the debugger
   738 void pp(intptr_t p)          { pp((void*)p); }
   739 void pp(oop p)               { pp((void*)p); }
   741 void help() {
   742   Command c("help");
   743   tty->print_cr("basic");
   744   tty->print_cr("  pp(void* p)   - try to make sense of p");
   745   tty->print_cr("  pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
   746   tty->print_cr("  ps()          - print current thread stack");
   747   tty->print_cr("  pss()         - print all thread stacks");
   748   tty->print_cr("  pm(int pc)    - print methodOop given compiled PC");
   749   tty->print_cr("  findm(intptr_t pc) - finds methodOop");
   750   tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
   752   tty->print_cr("misc.");
   753   tty->print_cr("  flush()       - flushes the log file");
   754   tty->print_cr("  events()      - dump last 50 events");
   757   tty->print_cr("compiler debugging");
   758   tty->print_cr("  debug()       - to set things up for compiler debugging");
   759   tty->print_cr("  ndebug()      - undo debug");
   760 }
   762 #if 0
   764 // BobV's command parser for debugging on windows when nothing else works.
   766 enum CommandID {
   767   CMDID_HELP,
   768   CMDID_QUIT,
   769   CMDID_HSFIND,
   770   CMDID_PSS,
   771   CMDID_PS,
   772   CMDID_PSF,
   773   CMDID_FINDM,
   774   CMDID_FINDNM,
   775   CMDID_PP,
   776   CMDID_BPT,
   777   CMDID_EXIT,
   778   CMDID_VERIFY,
   779   CMDID_THREADS,
   780   CMDID_ILLEGAL = 99
   781 };
   783 struct CommandParser {
   784    char *name;
   785    CommandID code;
   786    char *description;
   787 };
   789 struct CommandParser CommandList[] = {
   790   (char *)"help", CMDID_HELP, "  Dump this list",
   791   (char *)"quit", CMDID_QUIT, "  Return from this routine",
   792   (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
   793   (char *)"ps", CMDID_PS, "    Print Current Thread Stack Trace",
   794   (char *)"pss", CMDID_PSS, "   Print All Thread Stack Trace",
   795   (char *)"psf", CMDID_PSF, "   Print All Stack Frames",
   796   (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
   797   (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
   798   (char *)"pp", CMDID_PP, "    Find out something about a pointer",
   799   (char *)"break", CMDID_BPT, " Execute a breakpoint",
   800   (char *)"exitvm", CMDID_EXIT, "Exit the VM",
   801   (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
   802   (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
   803   (char *)0, CMDID_ILLEGAL
   804 };
   807 // get_debug_command()
   808 //
   809 // Read a command from standard input.
   810 // This is useful when you have a debugger
   811 // which doesn't support calling into functions.
   812 //
   813 void get_debug_command()
   814 {
   815   ssize_t count;
   816   int i,j;
   817   bool gotcommand;
   818   intptr_t addr;
   819   char buffer[256];
   820   nmethod *nm;
   821   methodOop m;
   823   tty->print_cr("You have entered the diagnostic command interpreter");
   824   tty->print("The supported commands are:\n");
   825   for ( i=0; ; i++ ) {
   826     if ( CommandList[i].code == CMDID_ILLEGAL )
   827       break;
   828     tty->print_cr("  %s \n", CommandList[i].name );
   829   }
   831   while ( 1 ) {
   832     gotcommand = false;
   833     tty->print("Please enter a command: ");
   834     count = scanf("%s", buffer) ;
   835     if ( count >=0 ) {
   836       for ( i=0; ; i++ ) {
   837         if ( CommandList[i].code == CMDID_ILLEGAL ) {
   838           if (!gotcommand) tty->print("Invalid command, please try again\n");
   839           break;
   840         }
   841         if ( strcmp(buffer, CommandList[i].name) == 0 ) {
   842           gotcommand = true;
   843           switch ( CommandList[i].code ) {
   844               case CMDID_PS:
   845                 ps();
   846                 break;
   847               case CMDID_PSS:
   848                 pss();
   849                 break;
   850               case CMDID_PSF:
   851                 psf();
   852                 break;
   853               case CMDID_FINDM:
   854                 tty->print("Please enter the hex addr to pass to findm: ");
   855                 scanf("%I64X", &addr);
   856                 m = (methodOop)findm(addr);
   857                 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
   858                 break;
   859               case CMDID_FINDNM:
   860                 tty->print("Please enter the hex addr to pass to findnm: ");
   861                 scanf("%I64X", &addr);
   862                 nm = (nmethod*)findnm(addr);
   863                 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
   864                 break;
   865               case CMDID_PP:
   866                 tty->print("Please enter the hex addr to pass to pp: ");
   867                 scanf("%I64X", &addr);
   868                 pp((void*)addr);
   869                 break;
   870               case CMDID_EXIT:
   871                 exit(0);
   872               case CMDID_HELP:
   873                 tty->print("Here are the supported commands: ");
   874                 for ( j=0; ; j++ ) {
   875                   if ( CommandList[j].code == CMDID_ILLEGAL )
   876                     break;
   877                   tty->print_cr("  %s --  %s\n", CommandList[j].name,
   878                                                  CommandList[j].description );
   879                 }
   880                 break;
   881               case CMDID_QUIT:
   882                 return;
   883                 break;
   884               case CMDID_BPT:
   885                 BREAKPOINT;
   886                 break;
   887               case CMDID_VERIFY:
   888                 verify();;
   889                 break;
   890               case CMDID_THREADS:
   891                 threads();;
   892                 break;
   893               case CMDID_HSFIND:
   894                 tty->print("Please enter the hex addr to pass to hsfind: ");
   895                 scanf("%I64X", &addr);
   896                 tty->print("Calling hsfind(0x%I64X)\n", addr);
   897                 hsfind(addr);
   898                 break;
   899               default:
   900               case CMDID_ILLEGAL:
   901                 break;
   902           }
   903         }
   904       }
   905     }
   906   }
   907 }
   908 #endif
   910 #endif // PRODUCT

mercurial