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