src/share/vm/utilities/debug.cpp

Wed, 02 Jan 2013 11:32:41 -0800

author
johnc
date
Wed, 02 Jan 2013 11:32:41 -0800
changeset 4384
b735136e0d82
parent 4299
f34d701e952e
child 4640
b6d5b3e50379
permissions
-rw-r--r--

8004132: SerialGC: ValidateMarkSweep broken when running GCOld
Summary: Remove bit-rotten ValidateMarkSweep functionality and flag.
Reviewed-by: johnc, jmasa
Contributed-by: tamao <tao.mao@oracle.com>

     1 /*
     2  * Copyright (c) 1997, 2012, 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/thread.inline.hpp"
    48 #include "runtime/vframe.hpp"
    49 #include "services/heapDumper.hpp"
    50 #include "utilities/defaultStream.hpp"
    51 #include "utilities/events.hpp"
    52 #include "utilities/top.hpp"
    53 #include "utilities/vmError.hpp"
    54 #ifdef TARGET_OS_FAMILY_linux
    55 # include "os_linux.inline.hpp"
    56 #endif
    57 #ifdef TARGET_OS_FAMILY_solaris
    58 # include "os_solaris.inline.hpp"
    59 #endif
    60 #ifdef TARGET_OS_FAMILY_windows
    61 # include "os_windows.inline.hpp"
    62 #endif
    63 #ifdef TARGET_OS_FAMILY_bsd
    64 # include "os_bsd.inline.hpp"
    65 #endif
    67 #ifndef ASSERT
    68 #  ifdef _DEBUG
    69    // NOTE: don't turn the lines below into a comment -- if you're getting
    70    // a compile error here, change the settings to define ASSERT
    71    ASSERT should be defined when _DEBUG is defined.  It is not intended to be used for debugging
    72    functions that do not slow down the system too much and thus can be left in optimized code.
    73    On the other hand, the code should not be included in a production version.
    74 #  endif // _DEBUG
    75 #endif // ASSERT
    78 #ifdef _DEBUG
    79 #  ifndef ASSERT
    80      configuration error: ASSERT must be defined in debug version
    81 #  endif // ASSERT
    82 #endif // _DEBUG
    85 #ifdef PRODUCT
    86 #  if -defined _DEBUG || -defined ASSERT
    87      configuration error: ASSERT et al. must not be defined in PRODUCT version
    88 #  endif
    89 #endif // PRODUCT
    91 FormatBufferResource::FormatBufferResource(const char * format, ...)
    92   : FormatBufferBase((char*)resource_allocate_bytes(RES_BUFSZ)) {
    93   va_list argp;
    94   va_start(argp, format);
    95   jio_vsnprintf(_buf, RES_BUFSZ, format, argp);
    96   va_end(argp);
    97 }
    99 void warning(const char* format, ...) {
   100   if (PrintWarnings) {
   101     FILE* const err = defaultStream::error_stream();
   102     jio_fprintf(err, "%s warning: ", VM_Version::vm_name());
   103     va_list ap;
   104     va_start(ap, format);
   105     vfprintf(err, format, ap);
   106     va_end(ap);
   107     fputc('\n', err);
   108   }
   109   if (BreakAtWarning) BREAKPOINT;
   110 }
   112 #ifndef PRODUCT
   114 #define is_token_break(ch) (isspace(ch) || (ch) == ',')
   116 static const char* last_file_name = NULL;
   117 static int         last_line_no   = -1;
   119 // assert/guarantee/... may happen very early during VM initialization.
   120 // Don't rely on anything that is initialized by Threads::create_vm(). For
   121 // example, don't use tty.
   122 bool error_is_suppressed(const char* file_name, int line_no) {
   123   // The following 1-element cache requires that passed-in
   124   // file names are always only constant literals.
   125   if (file_name == last_file_name && line_no == last_line_no)  return true;
   127   int file_name_len = (int)strlen(file_name);
   128   char separator = os::file_separator()[0];
   129   const char* base_name = strrchr(file_name, separator);
   130   if (base_name == NULL)
   131     base_name = file_name;
   133   // scan the SuppressErrorAt option
   134   const char* cp = SuppressErrorAt;
   135   for (;;) {
   136     const char* sfile;
   137     int sfile_len;
   138     int sline;
   139     bool noisy;
   140     while ((*cp) != '\0' && is_token_break(*cp))  cp++;
   141     if ((*cp) == '\0')  break;
   142     sfile = cp;
   143     while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':')  cp++;
   144     sfile_len = cp - sfile;
   145     if ((*cp) == ':')  cp++;
   146     sline = 0;
   147     while ((*cp) != '\0' && isdigit(*cp)) {
   148       sline *= 10;
   149       sline += (*cp) - '0';
   150       cp++;
   151     }
   152     // "file:line!" means the assert suppression is not silent
   153     noisy = ((*cp) == '!');
   154     while ((*cp) != '\0' && !is_token_break(*cp))  cp++;
   155     // match the line
   156     if (sline != 0) {
   157       if (sline != line_no)  continue;
   158     }
   159     // match the file
   160     if (sfile_len > 0) {
   161       const char* look = file_name;
   162       const char* look_max = file_name + file_name_len - sfile_len;
   163       const char* foundp;
   164       bool match = false;
   165       while (!match
   166              && (foundp = strchr(look, sfile[0])) != NULL
   167              && foundp <= look_max) {
   168         match = true;
   169         for (int i = 1; i < sfile_len; i++) {
   170           if (sfile[i] != foundp[i]) {
   171             match = false;
   172             break;
   173           }
   174         }
   175         look = foundp + 1;
   176       }
   177       if (!match)  continue;
   178     }
   179     // got a match!
   180     if (noisy) {
   181       fdStream out(defaultStream::output_fd());
   182       out.print_raw("[error suppressed at ");
   183       out.print_raw(base_name);
   184       char buf[16];
   185       jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
   186       out.print_raw_cr(buf);
   187     } else {
   188       // update 1-element cache for fast silent matches
   189       last_file_name = file_name;
   190       last_line_no   = line_no;
   191     }
   192     return true;
   193   }
   195   if (!is_error_reported()) {
   196     // print a friendly hint:
   197     fdStream out(defaultStream::output_fd());
   198     out.print_raw_cr("# To suppress the following error report, specify this argument");
   199     out.print_raw   ("# after -XX: or in .hotspotrc:  SuppressErrorAt=");
   200     out.print_raw   (base_name);
   201     char buf[16];
   202     jio_snprintf(buf, sizeof(buf), ":%d", line_no);
   203     out.print_raw_cr(buf);
   204   }
   205   return false;
   206 }
   208 #undef is_token_break
   210 #else
   212 // Place-holder for non-existent suppression check:
   213 #define error_is_suppressed(file_name, line_no) (false)
   215 #endif // !PRODUCT
   217 void report_vm_error(const char* file, int line, const char* error_msg,
   218                      const char* detail_msg)
   219 {
   220   if (Debugging || error_is_suppressed(file, line)) return;
   221   Thread* const thread = ThreadLocalStorage::get_thread_slow();
   222   VMError err(thread, file, line, error_msg, detail_msg);
   223   err.report_and_die();
   224 }
   226 void report_fatal(const char* file, int line, const char* message)
   227 {
   228   report_vm_error(file, line, "fatal error", message);
   229 }
   231 // Used by report_vm_out_of_memory to detect recursion.
   232 static jint _exiting_out_of_mem = 0;
   234 void report_vm_out_of_memory(const char* file, int line, size_t size,
   235                              const char* message) {
   236   if (Debugging) return;
   238   // We try to gather additional information for the first out of memory
   239   // error only; gathering additional data might cause an allocation and a
   240   // recursive out_of_memory condition.
   242   const jint exiting = 1;
   243   // If we succeed in changing the value, we're the first one in.
   244   bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
   246   if (first_time_here) {
   247     Thread* thread = ThreadLocalStorage::get_thread_slow();
   248     VMError(thread, file, line, size, message).report_and_die();
   249   }
   251   // Dump core and abort
   252   vm_abort(true);
   253 }
   255 void report_should_not_call(const char* file, int line) {
   256   report_vm_error(file, line, "ShouldNotCall()");
   257 }
   259 void report_should_not_reach_here(const char* file, int line) {
   260   report_vm_error(file, line, "ShouldNotReachHere()");
   261 }
   263 void report_should_not_reach_here2(const char* file, int line, const char* message) {
   264   report_vm_error(file, line, "ShouldNotReachHere()", message);
   265 }
   267 void report_unimplemented(const char* file, int line) {
   268   report_vm_error(file, line, "Unimplemented()");
   269 }
   271 void report_untested(const char* file, int line, const char* message) {
   272 #ifndef PRODUCT
   273   warning("Untested: %s in %s: %d\n", message, file, line);
   274 #endif // !PRODUCT
   275 }
   277 void report_out_of_shared_space(SharedSpaceType shared_space) {
   278   static const char* name[] = {
   279     "native memory for metadata",
   280     "shared read only space",
   281     "shared read write space",
   282     "shared miscellaneous data space"
   283   };
   284   static const char* flag[] = {
   285     "Metaspace",
   286     "SharedReadOnlySize",
   287     "SharedReadWriteSize",
   288     "SharedMiscDataSize"
   289   };
   291    warning("\nThe %s is not large enough\n"
   292            "to preload requested classes. Use -XX:%s=\n"
   293            "to increase the initial size of %s.\n",
   294            name[shared_space], flag[shared_space], name[shared_space]);
   295    exit(2);
   296 }
   298 void report_java_out_of_memory(const char* message) {
   299   static jint out_of_memory_reported = 0;
   301   // A number of threads may attempt to report OutOfMemoryError at around the
   302   // same time. To avoid dumping the heap or executing the data collection
   303   // commands multiple times we just do it once when the first threads reports
   304   // the error.
   305   if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
   306     // create heap dump before OnOutOfMemoryError commands are executed
   307     if (HeapDumpOnOutOfMemoryError) {
   308       tty->print_cr("java.lang.OutOfMemoryError: %s", message);
   309       HeapDumper::dump_heap_from_oome();
   310     }
   312     if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
   313       VMError err(message);
   314       err.report_java_out_of_memory();
   315     }
   316   }
   317 }
   319 static bool error_reported = false;
   321 // call this when the VM is dying--it might loosen some asserts
   322 void set_error_reported() {
   323   error_reported = true;
   324 }
   326 bool is_error_reported() {
   327     return error_reported;
   328 }
   330 #ifndef PRODUCT
   331 #include <signal.h>
   333 void test_error_handler(size_t test_num)
   334 {
   335   if (test_num == 0) return;
   337   // If asserts are disabled, use the corresponding guarantee instead.
   338   size_t n = test_num;
   339   NOT_DEBUG(if (n <= 2) n += 2);
   341   const char* const str = "hello";
   342   const size_t      num = (size_t)os::vm_page_size();
   344   const char* const eol = os::line_separator();
   345   const char* const msg = "this message should be truncated during formatting";
   347   // Keep this in sync with test/runtime/6888954/vmerrors.sh.
   348   switch (n) {
   349     case  1: assert(str == NULL, "expected null");
   350     case  2: assert(num == 1023 && *str == 'X',
   351                     err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
   352     case  3: guarantee(str == NULL, "expected null");
   353     case  4: guarantee(num == 1023 && *str == 'X',
   354                        err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
   355     case  5: fatal("expected null");
   356     case  6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
   357     case  7: fatal(err_msg("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
   358                            "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
   359                            "%s%s#    %s%s#    %s%s#    %s%s#    %s",
   360                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
   361                            msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
   362                            msg, eol, msg, eol, msg, eol, msg, eol, msg));
   363     case  8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
   364     case  9: ShouldNotCallThis();
   365     case 10: ShouldNotReachHere();
   366     case 11: Unimplemented();
   367     // This is last because it does not generate an hs_err* file on Windows.
   368     case 12: os::signal_raise(SIGSEGV);
   370     default: ShouldNotReachHere();
   371   }
   372 }
   373 #endif // !PRODUCT
   375 // ------ helper functions for debugging go here ------------
   377 // All debug entries should be wrapped with a stack allocated
   378 // Command object. It makes sure a resource mark is set and
   379 // flushes the logfile to prevent file sharing problems.
   381 class Command : public StackObj {
   382  private:
   383   ResourceMark rm;
   384   ResetNoHandleMark rnhm;
   385   HandleMark   hm;
   386   bool debug_save;
   387  public:
   388   static int level;
   389   Command(const char* str) {
   390     debug_save = Debugging;
   391     Debugging = true;
   392     if (level++ > 0)  return;
   393     tty->cr();
   394     tty->print_cr("\"Executing %s\"", str);
   395   }
   397   ~Command() {
   398         tty->flush();
   399         Debugging = debug_save;
   400         level--;
   401   }
   402 };
   404 int Command::level = 0;
   406 #ifndef PRODUCT
   408 extern "C" void blob(CodeBlob* cb) {
   409   Command c("blob");
   410   cb->print();
   411 }
   414 extern "C" void dump_vtable(address p) {
   415   Command c("dump_vtable");
   416   Klass* k = (Klass*)p;
   417   InstanceKlass::cast(k)->vtable()->print();
   418 }
   421 extern "C" void nm(intptr_t p) {
   422   // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
   423   Command c("nm");
   424   CodeBlob* cb = CodeCache::find_blob((address)p);
   425   if (cb == NULL) {
   426     tty->print_cr("NULL");
   427   } else {
   428     cb->print();
   429   }
   430 }
   433 extern "C" void disnm(intptr_t p) {
   434   Command c("disnm");
   435   CodeBlob* cb = CodeCache::find_blob((address) p);
   436   nmethod* nm = cb->as_nmethod_or_null();
   437   if (nm) {
   438     nm->print();
   439     Disassembler::decode(nm);
   440   } else {
   441     cb->print();
   442     Disassembler::decode(cb);
   443   }
   444 }
   447 extern "C" void printnm(intptr_t p) {
   448   char buffer[256];
   449   sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
   450   Command c(buffer);
   451   CodeBlob* cb = CodeCache::find_blob((address) p);
   452   if (cb->is_nmethod()) {
   453     nmethod* nm = (nmethod*)cb;
   454     nm->print_nmethod(true);
   455   }
   456 }
   459 extern "C" void universe() {
   460   Command c("universe");
   461   Universe::print();
   462 }
   465 extern "C" void verify() {
   466   // try to run a verify on the entire system
   467   // note: this may not be safe if we're not at a safepoint; for debugging,
   468   // this manipulates the safepoint settings to avoid assertion failures
   469   Command c("universe verify");
   470   bool safe = SafepointSynchronize::is_at_safepoint();
   471   if (!safe) {
   472     tty->print_cr("warning: not at safepoint -- verify may fail");
   473     SafepointSynchronize::set_is_at_safepoint();
   474   }
   475   // Ensure Eden top is correct before verification
   476   Universe::heap()->prepare_for_verify();
   477   Universe::verify();
   478   if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
   479 }
   482 extern "C" void pp(void* p) {
   483   Command c("pp");
   484   FlagSetting fl(PrintVMMessages, true);
   485   FlagSetting f2(DisplayVMOutput, true);
   486   if (Universe::heap()->is_in(p)) {
   487     oop obj = oop(p);
   488     obj->print();
   489   } else {
   490     tty->print(PTR_FORMAT, p);
   491   }
   492 }
   495 // pv: print vm-printable object
   496 extern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
   497 extern "C" void findpc(intptr_t x);
   499 #endif // !PRODUCT
   501 extern "C" void ps() { // print stack
   502   if (Thread::current() == NULL) return;
   503   Command c("ps");
   506   // Prints the stack of the current Java thread
   507   JavaThread* p = JavaThread::active();
   508   tty->print(" for thread: ");
   509   p->print();
   510   tty->cr();
   512   if (p->has_last_Java_frame()) {
   513     // If the last_Java_fp is set we are in C land and
   514     // can call the standard stack_trace function.
   515 #ifdef PRODUCT
   516     p->print_stack();
   517   } else {
   518     tty->print_cr("Cannot find the last Java frame, printing stack disabled.");
   519 #else // !PRODUCT
   520     p->trace_stack();
   521   } else {
   522     frame f = os::current_frame();
   523     RegisterMap reg_map(p);
   524     f = f.sender(&reg_map);
   525     tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
   526     p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
   527   pd_ps(f);
   528 #endif // PRODUCT
   529   }
   531 }
   533 extern "C" void pfl() {
   534   // print frame layout
   535   Command c("pfl");
   536   JavaThread* p = JavaThread::active();
   537   tty->print(" for thread: ");
   538   p->print();
   539   tty->cr();
   540   if (p->has_last_Java_frame()) {
   541     p->print_frame_layout();
   542   }
   543 }
   545 #ifndef PRODUCT
   547 extern "C" void psf() { // print stack frames
   548   {
   549     Command c("psf");
   550     JavaThread* p = JavaThread::active();
   551     tty->print(" for thread: ");
   552     p->print();
   553     tty->cr();
   554     if (p->has_last_Java_frame()) {
   555       p->trace_frames();
   556     }
   557   }
   558 }
   561 extern "C" void threads() {
   562   Command c("threads");
   563   Threads::print(false, true);
   564 }
   567 extern "C" void psd() {
   568   Command c("psd");
   569   SystemDictionary::print();
   570 }
   573 extern "C" void safepoints() {
   574   Command c("safepoints");
   575   SafepointSynchronize::print_state();
   576 }
   578 #endif // !PRODUCT
   580 extern "C" void pss() { // print all stacks
   581   if (Thread::current() == NULL) return;
   582   Command c("pss");
   583   Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true));
   584 }
   586 #ifndef PRODUCT
   588 extern "C" void debug() {               // to set things up for compiler debugging
   589   Command c("debug");
   590   WizardMode = true;
   591   PrintVMMessages = PrintCompilation = true;
   592   PrintInlining = PrintAssembly = true;
   593   tty->flush();
   594 }
   597 extern "C" void ndebug() {              // undo debug()
   598   Command c("ndebug");
   599   PrintCompilation = false;
   600   PrintInlining = PrintAssembly = false;
   601   tty->flush();
   602 }
   605 extern "C" void flush()  {
   606   Command c("flush");
   607   tty->flush();
   608 }
   610 extern "C" void events() {
   611   Command c("events");
   612   Events::print();
   613 }
   615 extern "C" Method* findm(intptr_t pc) {
   616   Command c("findm");
   617   nmethod* nm = CodeCache::find_nmethod((address)pc);
   618   return (nm == NULL) ? (Method*)NULL : nm->method();
   619 }
   622 extern "C" nmethod* findnm(intptr_t addr) {
   623   Command c("findnm");
   624   return  CodeCache::find_nmethod((address)addr);
   625 }
   627 static address same_page(address x, address y) {
   628   intptr_t page_bits = -os::vm_page_size();
   629   if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
   630     return x;
   631   } else if (x > y) {
   632     return (address)(intptr_t(y) | ~page_bits) + 1;
   633   } else {
   634     return (address)(intptr_t(y) & page_bits);
   635   }
   636 }
   639 // Another interface that isn't ambiguous in dbx.
   640 // Can we someday rename the other find to hsfind?
   641 extern "C" void hsfind(intptr_t x) {
   642   Command c("hsfind");
   643   os::print_location(tty, x, false);
   644 }
   647 extern "C" void find(intptr_t x) {
   648   Command c("find");
   649   os::print_location(tty, x, false);
   650 }
   653 extern "C" void findpc(intptr_t x) {
   654   Command c("findpc");
   655   os::print_location(tty, x, true);
   656 }
   659 // Need method pointer to find bcp, when not in permgen.
   660 extern "C" void findbcp(intptr_t method, intptr_t bcp) {
   661   Command c("findbcp");
   662   Method* mh = (Method*)method;
   663   if (!mh->is_native()) {
   664     tty->print_cr("bci_from(%p) = %d; print_codes():",
   665                         mh, mh->bci_from(address(bcp)));
   666     mh->print_codes_on(tty);
   667   }
   668 }
   670 // int versions of all methods to avoid having to type type casts in the debugger
   672 void pp(intptr_t p)          { pp((void*)p); }
   673 void pp(oop p)               { pp((void*)p); }
   675 void help() {
   676   Command c("help");
   677   tty->print_cr("basic");
   678   tty->print_cr("  pp(void* p)   - try to make sense of p");
   679   tty->print_cr("  pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
   680   tty->print_cr("  ps()          - print current thread stack");
   681   tty->print_cr("  pss()         - print all thread stacks");
   682   tty->print_cr("  pm(int pc)    - print Method* given compiled PC");
   683   tty->print_cr("  findm(intptr_t pc) - finds Method*");
   684   tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
   686   tty->print_cr("misc.");
   687   tty->print_cr("  flush()       - flushes the log file");
   688   tty->print_cr("  events()      - dump events from ring buffers");
   691   tty->print_cr("compiler debugging");
   692   tty->print_cr("  debug()       - to set things up for compiler debugging");
   693   tty->print_cr("  ndebug()      - undo debug");
   694 }
   696 #if 0
   698 // BobV's command parser for debugging on windows when nothing else works.
   700 enum CommandID {
   701   CMDID_HELP,
   702   CMDID_QUIT,
   703   CMDID_HSFIND,
   704   CMDID_PSS,
   705   CMDID_PS,
   706   CMDID_PSF,
   707   CMDID_FINDM,
   708   CMDID_FINDNM,
   709   CMDID_PP,
   710   CMDID_BPT,
   711   CMDID_EXIT,
   712   CMDID_VERIFY,
   713   CMDID_THREADS,
   714   CMDID_ILLEGAL = 99
   715 };
   717 struct CommandParser {
   718    char *name;
   719    CommandID code;
   720    char *description;
   721 };
   723 struct CommandParser CommandList[] = {
   724   (char *)"help", CMDID_HELP, "  Dump this list",
   725   (char *)"quit", CMDID_QUIT, "  Return from this routine",
   726   (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
   727   (char *)"ps", CMDID_PS, "    Print Current Thread Stack Trace",
   728   (char *)"pss", CMDID_PSS, "   Print All Thread Stack Trace",
   729   (char *)"psf", CMDID_PSF, "   Print All Stack Frames",
   730   (char *)"findm", CMDID_FINDM, " Find a Method* from a PC",
   731   (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
   732   (char *)"pp", CMDID_PP, "    Find out something about a pointer",
   733   (char *)"break", CMDID_BPT, " Execute a breakpoint",
   734   (char *)"exitvm", CMDID_EXIT, "Exit the VM",
   735   (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
   736   (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
   737   (char *)0, CMDID_ILLEGAL
   738 };
   741 // get_debug_command()
   742 //
   743 // Read a command from standard input.
   744 // This is useful when you have a debugger
   745 // which doesn't support calling into functions.
   746 //
   747 void get_debug_command()
   748 {
   749   ssize_t count;
   750   int i,j;
   751   bool gotcommand;
   752   intptr_t addr;
   753   char buffer[256];
   754   nmethod *nm;
   755   Method* m;
   757   tty->print_cr("You have entered the diagnostic command interpreter");
   758   tty->print("The supported commands are:\n");
   759   for ( i=0; ; i++ ) {
   760     if ( CommandList[i].code == CMDID_ILLEGAL )
   761       break;
   762     tty->print_cr("  %s \n", CommandList[i].name );
   763   }
   765   while ( 1 ) {
   766     gotcommand = false;
   767     tty->print("Please enter a command: ");
   768     count = scanf("%s", buffer) ;
   769     if ( count >=0 ) {
   770       for ( i=0; ; i++ ) {
   771         if ( CommandList[i].code == CMDID_ILLEGAL ) {
   772           if (!gotcommand) tty->print("Invalid command, please try again\n");
   773           break;
   774         }
   775         if ( strcmp(buffer, CommandList[i].name) == 0 ) {
   776           gotcommand = true;
   777           switch ( CommandList[i].code ) {
   778               case CMDID_PS:
   779                 ps();
   780                 break;
   781               case CMDID_PSS:
   782                 pss();
   783                 break;
   784               case CMDID_PSF:
   785                 psf();
   786                 break;
   787               case CMDID_FINDM:
   788                 tty->print("Please enter the hex addr to pass to findm: ");
   789                 scanf("%I64X", &addr);
   790                 m = (Method*)findm(addr);
   791                 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
   792                 break;
   793               case CMDID_FINDNM:
   794                 tty->print("Please enter the hex addr to pass to findnm: ");
   795                 scanf("%I64X", &addr);
   796                 nm = (nmethod*)findnm(addr);
   797                 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
   798                 break;
   799               case CMDID_PP:
   800                 tty->print("Please enter the hex addr to pass to pp: ");
   801                 scanf("%I64X", &addr);
   802                 pp((void*)addr);
   803                 break;
   804               case CMDID_EXIT:
   805                 exit(0);
   806               case CMDID_HELP:
   807                 tty->print("Here are the supported commands: ");
   808                 for ( j=0; ; j++ ) {
   809                   if ( CommandList[j].code == CMDID_ILLEGAL )
   810                     break;
   811                   tty->print_cr("  %s --  %s\n", CommandList[j].name,
   812                                                  CommandList[j].description );
   813                 }
   814                 break;
   815               case CMDID_QUIT:
   816                 return;
   817                 break;
   818               case CMDID_BPT:
   819                 BREAKPOINT;
   820                 break;
   821               case CMDID_VERIFY:
   822                 verify();;
   823                 break;
   824               case CMDID_THREADS:
   825                 threads();;
   826                 break;
   827               case CMDID_HSFIND:
   828                 tty->print("Please enter the hex addr to pass to hsfind: ");
   829                 scanf("%I64X", &addr);
   830                 tty->print("Calling hsfind(0x%I64X)\n", addr);
   831                 hsfind(addr);
   832                 break;
   833               default:
   834               case CMDID_ILLEGAL:
   835                 break;
   836           }
   837         }
   838       }
   839     }
   840   }
   841 }
   842 #endif
   844 #endif // !PRODUCT

mercurial