debug.cpp revision 1915:2f644f85485d
1216295Ssyrinx/*
2216295Ssyrinx * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3216295Ssyrinx * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4216295Ssyrinx *
5216295Ssyrinx * This code is free software; you can redistribute it and/or modify it
6216295Ssyrinx * under the terms of the GNU General Public License version 2 only, as
7216295Ssyrinx * published by the Free Software Foundation.
8216295Ssyrinx *
9216295Ssyrinx * This code is distributed in the hope that it will be useful, but WITHOUT
10216295Ssyrinx * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11216295Ssyrinx * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12216295Ssyrinx * version 2 for more details (a copy is included in the LICENSE file that
13216295Ssyrinx * accompanied this code).
14216295Ssyrinx *
15216295Ssyrinx * You should have received a copy of the GNU General Public License version
16216295Ssyrinx * 2 along with this work; if not, write to the Free Software Foundation,
17216295Ssyrinx * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18216295Ssyrinx *
19216295Ssyrinx * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20216295Ssyrinx * or visit www.oracle.com if you need additional information or have any
21216295Ssyrinx * questions.
22216295Ssyrinx *
23216295Ssyrinx */
24216295Ssyrinx
25216295Ssyrinx#include "precompiled.hpp"
26216295Ssyrinx#include "classfile/systemDictionary.hpp"
27216295Ssyrinx#include "code/codeCache.hpp"
28216295Ssyrinx#include "code/icBuffer.hpp"
29216295Ssyrinx#include "code/nmethod.hpp"
30216295Ssyrinx#include "code/vtableStubs.hpp"
31216295Ssyrinx#include "compiler/compileBroker.hpp"
32216295Ssyrinx#include "compiler/disassembler.hpp"
33216295Ssyrinx#include "gc_implementation/shared/markSweep.hpp"
34216295Ssyrinx#include "gc_interface/collectedHeap.hpp"
35216295Ssyrinx#include "interpreter/bytecodeHistogram.hpp"
36216295Ssyrinx#include "interpreter/interpreter.hpp"
37216295Ssyrinx#include "memory/resourceArea.hpp"
38216295Ssyrinx#include "memory/universe.hpp"
39216295Ssyrinx#include "oops/oop.inline.hpp"
40216295Ssyrinx#include "prims/privilegedStack.hpp"
41216295Ssyrinx#include "runtime/arguments.hpp"
42216295Ssyrinx#include "runtime/frame.hpp"
43216295Ssyrinx#include "runtime/java.hpp"
44216295Ssyrinx#include "runtime/sharedRuntime.hpp"
45216295Ssyrinx#include "runtime/stubCodeGenerator.hpp"
46216295Ssyrinx#include "runtime/stubRoutines.hpp"
47216295Ssyrinx#include "runtime/vframe.hpp"
48216295Ssyrinx#include "services/heapDumper.hpp"
49216295Ssyrinx#include "utilities/defaultStream.hpp"
50216295Ssyrinx#include "utilities/events.hpp"
51216295Ssyrinx#include "utilities/top.hpp"
52216295Ssyrinx#include "utilities/vmError.hpp"
53216295Ssyrinx#ifdef TARGET_OS_FAMILY_linux
54216295Ssyrinx# include "os_linux.inline.hpp"
55216295Ssyrinx# include "thread_linux.inline.hpp"
56216295Ssyrinx#endif
57216295Ssyrinx#ifdef TARGET_OS_FAMILY_solaris
58216295Ssyrinx# include "os_solaris.inline.hpp"
59216295Ssyrinx# include "thread_solaris.inline.hpp"
60216295Ssyrinx#endif
61216295Ssyrinx#ifdef TARGET_OS_FAMILY_windows
62216295Ssyrinx# include "os_windows.inline.hpp"
63216295Ssyrinx# include "thread_windows.inline.hpp"
64216295Ssyrinx#endif
65216295Ssyrinx
66216295Ssyrinx#ifndef ASSERT
67216295Ssyrinx#  ifdef _DEBUG
68216295Ssyrinx   // NOTE: don't turn the lines below into a comment -- if you're getting
69216295Ssyrinx   // a compile error here, change the settings to define ASSERT
70216295Ssyrinx   ASSERT should be defined when _DEBUG is defined.  It is not intended to be used for debugging
71216295Ssyrinx   functions that do not slow down the system too much and thus can be left in optimized code.
72216295Ssyrinx   On the other hand, the code should not be included in a production version.
73216295Ssyrinx#  endif // _DEBUG
74216295Ssyrinx#endif // ASSERT
75216295Ssyrinx
76216295Ssyrinx
77216295Ssyrinx#ifdef _DEBUG
78216295Ssyrinx#  ifndef ASSERT
79229933Ssyrinx     configuration error: ASSERT must be defined in debug version
80229933Ssyrinx#  endif // ASSERT
81229933Ssyrinx#endif // _DEBUG
82216295Ssyrinx
83216295Ssyrinx
84216295Ssyrinx#ifdef PRODUCT
85216295Ssyrinx#  if -defined _DEBUG || -defined ASSERT
86216295Ssyrinx     configuration error: ASSERT et al. must not be defined in PRODUCT version
87216295Ssyrinx#  endif
88216295Ssyrinx#endif // PRODUCT
89216295Ssyrinx
90216295Ssyrinx
91216295Ssyrinxvoid warning(const char* format, ...) {
92216295Ssyrinx  if (PrintWarnings) {
93216295Ssyrinx    // In case error happens before init or during shutdown
94216295Ssyrinx    if (tty == NULL) ostream_init();
95216295Ssyrinx
96216295Ssyrinx    tty->print("%s warning: ", VM_Version::vm_name());
97216295Ssyrinx    va_list ap;
98216295Ssyrinx    va_start(ap, format);
99216295Ssyrinx    tty->vprint_cr(format, ap);
100216295Ssyrinx    va_end(ap);
101216295Ssyrinx  }
102216295Ssyrinx  if (BreakAtWarning) BREAKPOINT;
103216295Ssyrinx}
104216295Ssyrinx
105216295Ssyrinx#ifndef PRODUCT
106216295Ssyrinx
107216295Ssyrinx#define is_token_break(ch) (isspace(ch) || (ch) == ',')
108216295Ssyrinx
109216295Ssyrinxstatic const char* last_file_name = NULL;
110216295Ssyrinxstatic int         last_line_no   = -1;
111216295Ssyrinx
112216295Ssyrinx// assert/guarantee/... may happen very early during VM initialization.
113216295Ssyrinx// Don't rely on anything that is initialized by Threads::create_vm(). For
114216295Ssyrinx// example, don't use tty.
115216295Ssyrinxbool error_is_suppressed(const char* file_name, int line_no) {
116216295Ssyrinx  // The following 1-element cache requires that passed-in
117216295Ssyrinx  // file names are always only constant literals.
118216295Ssyrinx  if (file_name == last_file_name && line_no == last_line_no)  return true;
119216295Ssyrinx
120216295Ssyrinx  int file_name_len = (int)strlen(file_name);
121216295Ssyrinx  char separator = os::file_separator()[0];
122216295Ssyrinx  const char* base_name = strrchr(file_name, separator);
123216295Ssyrinx  if (base_name == NULL)
124216295Ssyrinx    base_name = file_name;
125216295Ssyrinx
126216295Ssyrinx  // scan the SuppressErrorAt option
127216295Ssyrinx  const char* cp = SuppressErrorAt;
128216295Ssyrinx  for (;;) {
129216295Ssyrinx    const char* sfile;
130216295Ssyrinx    int sfile_len;
131216295Ssyrinx    int sline;
132216295Ssyrinx    bool noisy;
133216295Ssyrinx    while ((*cp) != '\0' && is_token_break(*cp))  cp++;
134216295Ssyrinx    if ((*cp) == '\0')  break;
135216295Ssyrinx    sfile = cp;
136216295Ssyrinx    while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':')  cp++;
137216295Ssyrinx    sfile_len = cp - sfile;
138216295Ssyrinx    if ((*cp) == ':')  cp++;
139216295Ssyrinx    sline = 0;
140216295Ssyrinx    while ((*cp) != '\0' && isdigit(*cp)) {
141216295Ssyrinx      sline *= 10;
142216295Ssyrinx      sline += (*cp) - '0';
143216295Ssyrinx      cp++;
144216295Ssyrinx    }
145216295Ssyrinx    // "file:line!" means the assert suppression is not silent
146216295Ssyrinx    noisy = ((*cp) == '!');
147216295Ssyrinx    while ((*cp) != '\0' && !is_token_break(*cp))  cp++;
148216295Ssyrinx    // match the line
149216295Ssyrinx    if (sline != 0) {
150216295Ssyrinx      if (sline != line_no)  continue;
151216295Ssyrinx    }
152216295Ssyrinx    // match the file
153216295Ssyrinx    if (sfile_len > 0) {
154229933Ssyrinx      const char* look = file_name;
155216295Ssyrinx      const char* look_max = file_name + file_name_len - sfile_len;
156216295Ssyrinx      const char* foundp;
157216295Ssyrinx      bool match = false;
158216295Ssyrinx      while (!match
159216295Ssyrinx             && (foundp = strchr(look, sfile[0])) != NULL
160216295Ssyrinx             && foundp <= look_max) {
161216295Ssyrinx        match = true;
162216295Ssyrinx        for (int i = 1; i < sfile_len; i++) {
163216295Ssyrinx          if (sfile[i] != foundp[i]) {
164216295Ssyrinx            match = false;
165216295Ssyrinx            break;
166216295Ssyrinx          }
167216295Ssyrinx        }
168216295Ssyrinx        look = foundp + 1;
169216295Ssyrinx      }
170216295Ssyrinx      if (!match)  continue;
171216295Ssyrinx    }
172216295Ssyrinx    // got a match!
173216295Ssyrinx    if (noisy) {
174216295Ssyrinx      fdStream out(defaultStream::output_fd());
175216295Ssyrinx      out.print_raw("[error suppressed at ");
176216295Ssyrinx      out.print_raw(base_name);
177216295Ssyrinx      char buf[16];
178216295Ssyrinx      jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
179216295Ssyrinx      out.print_raw_cr(buf);
180216295Ssyrinx    } else {
181216295Ssyrinx      // update 1-element cache for fast silent matches
182216295Ssyrinx      last_file_name = file_name;
183216295Ssyrinx      last_line_no   = line_no;
184216295Ssyrinx    }
185216295Ssyrinx    return true;
186216295Ssyrinx  }
187216295Ssyrinx
188216295Ssyrinx  if (!is_error_reported()) {
189216295Ssyrinx    // print a friendly hint:
190216295Ssyrinx    fdStream out(defaultStream::output_fd());
191216295Ssyrinx    out.print_raw_cr("# To suppress the following error report, specify this argument");
192216295Ssyrinx    out.print_raw   ("# after -XX: or in .hotspotrc:  SuppressErrorAt=");
193216295Ssyrinx    out.print_raw   (base_name);
194216295Ssyrinx    char buf[16];
195216295Ssyrinx    jio_snprintf(buf, sizeof(buf), ":%d", line_no);
196216295Ssyrinx    out.print_raw_cr(buf);
197216295Ssyrinx  }
198216295Ssyrinx  return false;
199216295Ssyrinx}
200216295Ssyrinx
201216295Ssyrinx#undef is_token_break
202216295Ssyrinx
203216295Ssyrinx#else
204216295Ssyrinx
205216295Ssyrinx// Place-holder for non-existent suppression check:
206216295Ssyrinx#define error_is_suppressed(file_name, line_no) (false)
207216295Ssyrinx
208216295Ssyrinx#endif //PRODUCT
209216295Ssyrinx
210216295Ssyrinxvoid report_vm_error(const char* file, int line, const char* error_msg,
211216295Ssyrinx                     const char* detail_msg)
212216295Ssyrinx{
213216295Ssyrinx  if (Debugging || error_is_suppressed(file, line)) return;
214216295Ssyrinx  Thread* const thread = ThreadLocalStorage::get_thread_slow();
215216295Ssyrinx  VMError err(thread, file, line, error_msg, detail_msg);
216216295Ssyrinx  err.report_and_die();
217216295Ssyrinx}
218216295Ssyrinx
219216295Ssyrinxvoid report_fatal(const char* file, int line, const char* message)
220216295Ssyrinx{
221216295Ssyrinx  report_vm_error(file, line, "fatal error", message);
222216295Ssyrinx}
223216295Ssyrinx
224216295Ssyrinx// Used by report_vm_out_of_memory to detect recursion.
225216295Ssyrinxstatic jint _exiting_out_of_mem = 0;
226216295Ssyrinx
227216295Ssyrinxvoid report_vm_out_of_memory(const char* file, int line, size_t size,
228216295Ssyrinx                             const char* message) {
229216295Ssyrinx  if (Debugging || error_is_suppressed(file, line)) return;
230216295Ssyrinx
231216295Ssyrinx  // We try to gather additional information for the first out of memory
232216295Ssyrinx  // error only; gathering additional data might cause an allocation and a
233216295Ssyrinx  // recursive out_of_memory condition.
234216295Ssyrinx
235216295Ssyrinx  const jint exiting = 1;
236216295Ssyrinx  // If we succeed in changing the value, we're the first one in.
237216295Ssyrinx  bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
238216295Ssyrinx
239216295Ssyrinx  if (first_time_here) {
240216295Ssyrinx    Thread* thread = ThreadLocalStorage::get_thread_slow();
241216295Ssyrinx    VMError(thread, file, line, size, message).report_and_die();
242216295Ssyrinx  }
243216295Ssyrinx
244216295Ssyrinx  // Dump core and abort
245216295Ssyrinx  vm_abort(true);
246216295Ssyrinx}
247216295Ssyrinx
248216295Ssyrinxvoid report_should_not_call(const char* file, int line) {
249216295Ssyrinx  report_vm_error(file, line, "ShouldNotCall()");
250216295Ssyrinx}
251216295Ssyrinx
252228990Suqsvoid report_should_not_reach_here(const char* file, int line) {
253216295Ssyrinx  report_vm_error(file, line, "ShouldNotReachHere()");
254228990Suqs}
255216295Ssyrinx
256216295Ssyrinxvoid report_unimplemented(const char* file, int line) {
257216295Ssyrinx  report_vm_error(file, line, "Unimplemented()");
258216295Ssyrinx}
259216295Ssyrinx
260216295Ssyrinxvoid report_untested(const char* file, int line, const char* message) {
261216295Ssyrinx#ifndef PRODUCT
262216295Ssyrinx  warning("Untested: %s in %s: %d\n", message, file, line);
263216295Ssyrinx#endif // PRODUCT
264216295Ssyrinx}
265216295Ssyrinx
266216295Ssyrinxvoid report_java_out_of_memory(const char* message) {
267216295Ssyrinx  static jint out_of_memory_reported = 0;
268216295Ssyrinx
269216295Ssyrinx  // A number of threads may attempt to report OutOfMemoryError at around the
270216295Ssyrinx  // same time. To avoid dumping the heap or executing the data collection
271216295Ssyrinx  // commands multiple times we just do it once when the first threads reports
272216295Ssyrinx  // the error.
273216295Ssyrinx  if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
274216295Ssyrinx    // create heap dump before OnOutOfMemoryError commands are executed
275216295Ssyrinx    if (HeapDumpOnOutOfMemoryError) {
276216295Ssyrinx      tty->print_cr("java.lang.OutOfMemoryError: %s", message);
277216295Ssyrinx      HeapDumper::dump_heap_from_oome();
278216295Ssyrinx    }
279216295Ssyrinx
280216295Ssyrinx    if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
281216295Ssyrinx      VMError err(message);
282216295Ssyrinx      err.report_java_out_of_memory();
283216295Ssyrinx    }
284216295Ssyrinx  }
285216295Ssyrinx}
286216295Ssyrinx
287216295Ssyrinx
288216295Ssyrinxextern "C" void ps();
289216295Ssyrinx
290216295Ssyrinxstatic bool error_reported = false;
291216295Ssyrinx
292216295Ssyrinx// call this when the VM is dying--it might loosen some asserts
293216295Ssyrinxvoid set_error_reported() {
294216295Ssyrinx  error_reported = true;
295216295Ssyrinx}
296216295Ssyrinx
297216295Ssyrinxbool is_error_reported() {
298216295Ssyrinx    return error_reported;
299216295Ssyrinx}
300216295Ssyrinx
301216295Ssyrinx#ifndef PRODUCT
302216295Ssyrinx#include <signal.h>
303216295Ssyrinx
304216295Ssyrinxvoid test_error_handler(size_t test_num)
305216295Ssyrinx{
306216295Ssyrinx  if (test_num == 0) return;
307216295Ssyrinx
308216295Ssyrinx  // If asserts are disabled, use the corresponding guarantee instead.
309216295Ssyrinx  size_t n = test_num;
310216295Ssyrinx  NOT_DEBUG(if (n <= 2) n += 2);
311216295Ssyrinx
312216295Ssyrinx  const char* const str = "hello";
313216295Ssyrinx  const size_t      num = (size_t)os::vm_page_size();
314216295Ssyrinx
315216295Ssyrinx  const char* const eol = os::line_separator();
316216295Ssyrinx  const char* const msg = "this message should be truncated during formatting";
317216295Ssyrinx
318216295Ssyrinx  // Keep this in sync with test/runtime/6888954/vmerrors.sh.
319216295Ssyrinx  switch (n) {
320216295Ssyrinx    case  1: assert(str == NULL, "expected null");
321216295Ssyrinx    case  2: assert(num == 1023 && *str == 'X',
322216295Ssyrinx                    err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
323216295Ssyrinx    case  3: guarantee(str == NULL, "expected null");
324216295Ssyrinx    case  4: guarantee(num == 1023 && *str == 'X',
325216295Ssyrinx                       err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
326216295Ssyrinx    case  5: fatal("expected null");
327216295Ssyrinx    case  6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
328216295Ssyrinx    case  7: fatal(err_msg("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
329216295Ssyrinx                           "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
330216295Ssyrinx                           "%s%s#    %s%s#    %s%s#    %s%s#    %s",
331216295Ssyrinx                           msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
332216295Ssyrinx                           msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
333216295Ssyrinx                           msg, eol, msg, eol, msg, eol, msg, eol, msg));
334216295Ssyrinx    case  8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
335216295Ssyrinx    case  9: ShouldNotCallThis();
336216295Ssyrinx    case 10: ShouldNotReachHere();
337216295Ssyrinx    case 11: Unimplemented();
338216295Ssyrinx    // This is last because it does not generate an hs_err* file on Windows.
339216295Ssyrinx    case 12: os::signal_raise(SIGSEGV);
340216295Ssyrinx
341216295Ssyrinx    default: ShouldNotReachHere();
342216295Ssyrinx  }
343216295Ssyrinx}
344216295Ssyrinx#endif // #ifndef PRODUCT
345216295Ssyrinx
346216295Ssyrinx// ------ helper functions for debugging go here ------------
347216295Ssyrinx
348216295Ssyrinx#ifndef PRODUCT
349216295Ssyrinx// All debug entries should be wrapped with a stack allocated
350216295Ssyrinx// Command object. It makes sure a resource mark is set and
351216295Ssyrinx// flushes the logfile to prevent file sharing problems.
352216295Ssyrinx
353216295Ssyrinxclass Command : public StackObj {
354216295Ssyrinx private:
355216295Ssyrinx  ResourceMark rm;
356216295Ssyrinx  ResetNoHandleMark rnhm;
357216295Ssyrinx  HandleMark   hm;
358216295Ssyrinx  bool debug_save;
359216295Ssyrinx public:
360216295Ssyrinx  static int level;
361216295Ssyrinx  Command(const char* str) {
362216295Ssyrinx    debug_save = Debugging;
363216295Ssyrinx    Debugging = true;
364216295Ssyrinx    if (level++ > 0)  return;
365216295Ssyrinx    tty->cr();
366216295Ssyrinx    tty->print_cr("\"Executing %s\"", str);
367216295Ssyrinx  }
368216295Ssyrinx
369216295Ssyrinx  ~Command() { tty->flush(); Debugging = debug_save; level--; }
370216295Ssyrinx};
371216295Ssyrinx
372216295Ssyrinxint Command::level = 0;
373216295Ssyrinx
374216295Ssyrinxextern "C" void blob(CodeBlob* cb) {
375216295Ssyrinx  Command c("blob");
376216295Ssyrinx  cb->print();
377216295Ssyrinx}
378216295Ssyrinx
379216295Ssyrinx
380216295Ssyrinxextern "C" void dump_vtable(address p) {
381216295Ssyrinx  Command c("dump_vtable");
382216295Ssyrinx  klassOop k = (klassOop)p;
383216295Ssyrinx  instanceKlass::cast(k)->vtable()->print();
384216295Ssyrinx}
385216295Ssyrinx
386216295Ssyrinx
387216295Ssyrinxextern "C" void nm(intptr_t p) {
388216295Ssyrinx  // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
389216295Ssyrinx  Command c("nm");
390216295Ssyrinx  CodeBlob* cb = CodeCache::find_blob((address)p);
391216295Ssyrinx  if (cb == NULL) {
392216295Ssyrinx    tty->print_cr("NULL");
393216295Ssyrinx  } else {
394216295Ssyrinx    cb->print();
395216295Ssyrinx  }
396216295Ssyrinx}
397311594Sngie
398216295Ssyrinx
399216295Ssyrinxextern "C" void disnm(intptr_t p) {
400216295Ssyrinx  Command c("disnm");
401216295Ssyrinx  CodeBlob* cb = CodeCache::find_blob((address) p);
402229933Ssyrinx  nmethod* nm = cb->as_nmethod_or_null();
403312049Sngie  if (nm) {
404216295Ssyrinx    nm->print();
405216295Ssyrinx    Disassembler::decode(nm);
406216295Ssyrinx  } else {
407216295Ssyrinx    cb->print();
408216295Ssyrinx    Disassembler::decode(cb);
409312049Sngie  }
410312049Sngie}
411216295Ssyrinx
412312049Sngie
413216295Ssyrinxextern "C" void printnm(intptr_t p) {
414216295Ssyrinx  char buffer[256];
415216295Ssyrinx  sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
416216295Ssyrinx  Command c(buffer);
417216295Ssyrinx  CodeBlob* cb = CodeCache::find_blob((address) p);
418216295Ssyrinx  if (cb->is_nmethod()) {
419216295Ssyrinx    nmethod* nm = (nmethod*)cb;
420312049Sngie    nm->print_nmethod(true);
421312049Sngie  }
422216295Ssyrinx}
423312049Sngie
424216295Ssyrinx
425216295Ssyrinxextern "C" void universe() {
426216295Ssyrinx  Command c("universe");
427216295Ssyrinx  Universe::print();
428216295Ssyrinx}
429216295Ssyrinx
430312049Sngie
431216295Ssyrinxextern "C" void verify() {
432216295Ssyrinx  // try to run a verify on the entire system
433216295Ssyrinx  // note: this may not be safe if we're not at a safepoint; for debugging,
434216295Ssyrinx  // this manipulates the safepoint settings to avoid assertion failures
435216295Ssyrinx  Command c("universe verify");
436216295Ssyrinx  bool safe = SafepointSynchronize::is_at_safepoint();
437216295Ssyrinx  if (!safe) {
438216295Ssyrinx    tty->print_cr("warning: not at safepoint -- verify may fail");
439216295Ssyrinx    SafepointSynchronize::set_is_at_safepoint();
440216295Ssyrinx  }
441216295Ssyrinx  // Ensure Eden top is correct before verification
442216295Ssyrinx  Universe::heap()->prepare_for_verify();
443216295Ssyrinx  Universe::verify(true);
444216295Ssyrinx  if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
445216295Ssyrinx}
446216295Ssyrinx
447216295Ssyrinx
448216295Ssyrinxextern "C" void pp(void* p) {
449216295Ssyrinx  Command c("pp");
450216295Ssyrinx  FlagSetting fl(PrintVMMessages, true);
451216295Ssyrinx  if (Universe::heap()->is_in(p)) {
452216295Ssyrinx    oop obj = oop(p);
453216295Ssyrinx    obj->print();
454216295Ssyrinx  } else {
455216295Ssyrinx    tty->print("%#p", p);
456216295Ssyrinx  }
457216295Ssyrinx}
458216295Ssyrinx
459216295Ssyrinx
460216295Ssyrinx// pv: print vm-printable object
461216295Ssyrinxextern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
462216295Ssyrinxextern "C" void findpc(intptr_t x);
463216295Ssyrinx
464216295Ssyrinxextern "C" void ps() { // print stack
465216295Ssyrinx  Command c("ps");
466216295Ssyrinx
467228990Suqs
468216295Ssyrinx  // Prints the stack of the current Java thread
469229933Ssyrinx  JavaThread* p = JavaThread::active();
470216295Ssyrinx  tty->print(" for thread: ");
471229933Ssyrinx  p->print();
472229933Ssyrinx  tty->cr();
473229933Ssyrinx
474229933Ssyrinx  if (p->has_last_Java_frame()) {
475216295Ssyrinx    // If the last_Java_fp is set we are in C land and
476229933Ssyrinx    // can call the standard stack_trace function.
477229933Ssyrinx    p->trace_stack();
478216295Ssyrinx  } else {
479216295Ssyrinx    frame f = os::current_frame();
480216295Ssyrinx    RegisterMap reg_map(p);
481216295Ssyrinx    f = f.sender(&reg_map);
482216295Ssyrinx    tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
483216295Ssyrinx    p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
484216295Ssyrinx  pd_ps(f);
485229933Ssyrinx  }
486229933Ssyrinx
487229933Ssyrinx}
488229933Ssyrinx
489216295Ssyrinx
490216295Ssyrinxextern "C" void psf() { // print stack frames
491216295Ssyrinx  {
492216295Ssyrinx    Command c("psf");
493216295Ssyrinx    JavaThread* p = JavaThread::active();
494216295Ssyrinx    tty->print(" for thread: ");
495216295Ssyrinx    p->print();
496216295Ssyrinx    tty->cr();
497216295Ssyrinx    if (p->has_last_Java_frame()) {
498229933Ssyrinx      p->trace_frames();
499229933Ssyrinx    }
500216295Ssyrinx  }
501229933Ssyrinx}
502216295Ssyrinx
503216295Ssyrinx
504216295Ssyrinxextern "C" void threads() {
505229933Ssyrinx  Command c("threads");
506216295Ssyrinx  Threads::print(false, true);
507312049Sngie}
508312049Sngie
509229933Ssyrinx
510312049Sngieextern "C" void psd() {
511229933Ssyrinx  Command c("psd");
512229933Ssyrinx  SystemDictionary::print();
513229933Ssyrinx}
514229933Ssyrinx
515229933Ssyrinx
516229933Ssyrinxextern "C" void safepoints() {
517312049Sngie  Command c("safepoints");
518216295Ssyrinx  SafepointSynchronize::print_state();
519216295Ssyrinx}
520216295Ssyrinx
521216295Ssyrinx
522216295Ssyrinxextern "C" void pss() { // print all stacks
523216295Ssyrinx  Command c("pss");
524312049Sngie  Threads::print(true, true);
525216295Ssyrinx}
526216295Ssyrinx
527312049Sngie
528312049Sngieextern "C" void debug() {               // to set things up for compiler debugging
529216295Ssyrinx  Command c("debug");
530216295Ssyrinx  WizardMode = true;
531311594Sngie  PrintVMMessages = PrintCompilation = true;
532216295Ssyrinx  PrintInlining = PrintAssembly = true;
533216295Ssyrinx  tty->flush();
534216295Ssyrinx}
535216295Ssyrinx
536216295Ssyrinx
537216295Ssyrinxextern "C" void ndebug() {              // undo debug()
538216295Ssyrinx  Command c("ndebug");
539312049Sngie  PrintCompilation = false;
540229933Ssyrinx  PrintInlining = PrintAssembly = false;
541216295Ssyrinx  tty->flush();
542216295Ssyrinx}
543312049Sngie
544312049Sngie
545216295Ssyrinxextern "C" void flush()  {
546216295Ssyrinx  Command c("flush");
547216295Ssyrinx  tty->flush();
548216295Ssyrinx}
549216295Ssyrinx
550216295Ssyrinx
551216295Ssyrinxextern "C" void events() {
552216295Ssyrinx  Command c("events");
553216295Ssyrinx  Events::print_last(tty, 50);
554216295Ssyrinx}
555216295Ssyrinx
556216295Ssyrinx
557216295Ssyrinxextern "C" void nevents(int n) {
558216295Ssyrinx  Command c("events");
559216295Ssyrinx  Events::print_last(tty, n);
560216295Ssyrinx}
561216295Ssyrinx
562216295Ssyrinx
563216295Ssyrinx// Given a heap address that was valid before the most recent GC, if
564216295Ssyrinx// the oop that used to contain it is still live, prints the new
565216295Ssyrinx// location of the oop and the address. Useful for tracking down
566216295Ssyrinx// certain kinds of naked oop and oop map bugs.
567311594Sngieextern "C" void pnl(intptr_t old_heap_addr) {
568216295Ssyrinx  // Print New Location of old heap address
569216295Ssyrinx  Command c("pnl");
570216295Ssyrinx#ifndef VALIDATE_MARK_SWEEP
571216295Ssyrinx  tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
572216295Ssyrinx#else
573216295Ssyrinx  MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
574216295Ssyrinx#endif
575216295Ssyrinx}
576216295Ssyrinx
577216295Ssyrinx
578216295Ssyrinxextern "C" methodOop findm(intptr_t pc) {
579216295Ssyrinx  Command c("findm");
580216295Ssyrinx  nmethod* nm = CodeCache::find_nmethod((address)pc);
581216295Ssyrinx  return (nm == NULL) ? (methodOop)NULL : nm->method();
582216295Ssyrinx}
583216295Ssyrinx
584216295Ssyrinx
585216295Ssyrinxextern "C" nmethod* findnm(intptr_t addr) {
586216295Ssyrinx  Command c("findnm");
587216295Ssyrinx  return  CodeCache::find_nmethod((address)addr);
588216295Ssyrinx}
589216295Ssyrinx
590216295Ssyrinxstatic address same_page(address x, address y) {
591216295Ssyrinx  intptr_t page_bits = -os::vm_page_size();
592216295Ssyrinx  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
593216295Ssyrinx    return x;
594216295Ssyrinx  } else if (x > y) {
595216295Ssyrinx    return (address)(intptr_t(y) | ~page_bits) + 1;
596216295Ssyrinx  } else {
597216295Ssyrinx    return (address)(intptr_t(y) & page_bits);
598216295Ssyrinx  }
599216295Ssyrinx}
600216295Ssyrinx
601216295Ssyrinxclass LookForRefInGenClosure : public OopsInGenClosure {
602216295Ssyrinxpublic:
603216295Ssyrinx  oop target;
604216295Ssyrinx  void do_oop(oop* o) {
605216295Ssyrinx    if (o != NULL && *o == target) {
606216295Ssyrinx      tty->print_cr(INTPTR_FORMAT, o);
607216295Ssyrinx    }
608216295Ssyrinx  }
609216295Ssyrinx  void do_oop(narrowOop* o) { ShouldNotReachHere(); }
610216295Ssyrinx};
611216295Ssyrinx
612216295Ssyrinx
613216295Ssyrinxclass LookForRefInObjectClosure : public ObjectClosure {
614216295Ssyrinxprivate:
615310561Sngie  LookForRefInGenClosure look_in_object;
616310561Sngiepublic:
617216295Ssyrinx  LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
618216295Ssyrinx  void do_object(oop obj) {
619216295Ssyrinx    obj->oop_iterate(&look_in_object);
620216295Ssyrinx  }
621216295Ssyrinx};
622216295Ssyrinx
623216295Ssyrinx
624216295Ssyrinxstatic void findref(intptr_t x) {
625216295Ssyrinx  CollectedHeap *ch = Universe::heap();
626216295Ssyrinx  LookForRefInGenClosure lookFor;
627216295Ssyrinx  lookFor.target = (oop) x;
628216295Ssyrinx  LookForRefInObjectClosure look_in_object((oop) x);
629310561Sngie
630216295Ssyrinx  tty->print_cr("Searching heap:");
631216295Ssyrinx  ch->object_iterate(&look_in_object);
632216295Ssyrinx
633216295Ssyrinx  tty->print_cr("Searching strong roots:");
634216295Ssyrinx  Universe::oops_do(&lookFor, false);
635216295Ssyrinx  JNIHandles::oops_do(&lookFor);   // Global (strong) JNI handles
636216295Ssyrinx  Threads::oops_do(&lookFor, NULL);
637216295Ssyrinx  ObjectSynchronizer::oops_do(&lookFor);
638216295Ssyrinx  //FlatProfiler::oops_do(&lookFor);
639216295Ssyrinx  SystemDictionary::oops_do(&lookFor);
640216295Ssyrinx
641216295Ssyrinx  tty->print_cr("Searching code cache:");
642216295Ssyrinx  CodeCache::oops_do(&lookFor);
643216295Ssyrinx
644216295Ssyrinx  tty->print_cr("Done.");
645216295Ssyrinx}
646311594Sngie
647216295Ssyrinxclass FindClassObjectClosure: public ObjectClosure {
648216295Ssyrinx  private:
649216295Ssyrinx    const char* _target;
650216295Ssyrinx  public:
651216295Ssyrinx    FindClassObjectClosure(const char name[])  { _target = name; }
652216295Ssyrinx
653216295Ssyrinx    virtual void do_object(oop obj) {
654216295Ssyrinx      if (obj->is_klass()) {
655216295Ssyrinx        Klass* k = klassOop(obj)->klass_part();
656216295Ssyrinx        if (k->name() != NULL) {
657216295Ssyrinx          ResourceMark rm;
658216295Ssyrinx          const char* ext = k->external_name();
659216295Ssyrinx          if ( strcmp(_target, ext) == 0 ) {
660216295Ssyrinx            tty->print_cr("Found " INTPTR_FORMAT, obj);
661216295Ssyrinx            obj->print();
662216295Ssyrinx          }
663216295Ssyrinx        }
664216295Ssyrinx      }
665216295Ssyrinx    }
666216295Ssyrinx};
667216295Ssyrinx
668216295Ssyrinx//
669216295Ssyrinxextern "C" void findclass(const char name[]) {
670216295Ssyrinx  Command c("findclass");
671216295Ssyrinx  if (name != NULL) {
672216295Ssyrinx    tty->print_cr("Finding class %s -> ", name);
673216295Ssyrinx    FindClassObjectClosure srch(name);
674216295Ssyrinx    Universe::heap()->permanent_object_iterate(&srch);
675216295Ssyrinx  }
676216295Ssyrinx}
677216295Ssyrinx
678216295Ssyrinx// Another interface that isn't ambiguous in dbx.
679216295Ssyrinx// Can we someday rename the other find to hsfind?
680216295Ssyrinxextern "C" void hsfind(intptr_t x) {
681216295Ssyrinx  Command c("hsfind");
682216295Ssyrinx  os::print_location(tty, x, false);
683216295Ssyrinx}
684216295Ssyrinx
685216295Ssyrinx
686216295Ssyrinxextern "C" void hsfindref(intptr_t x) {
687216295Ssyrinx  Command c("hsfindref");
688216295Ssyrinx  findref(x);
689216295Ssyrinx}
690216295Ssyrinx
691216295Ssyrinxextern "C" void find(intptr_t x) {
692216295Ssyrinx  Command c("find");
693216295Ssyrinx  os::print_location(tty, x, false);
694311594Sngie}
695216295Ssyrinx
696216295Ssyrinx
697216295Ssyrinxextern "C" void findpc(intptr_t x) {
698216295Ssyrinx  Command c("findpc");
699216295Ssyrinx  os::print_location(tty, x, true);
700216295Ssyrinx}
701216295Ssyrinx
702216295Ssyrinx
703216295Ssyrinx// int versions of all methods to avoid having to type type casts in the debugger
704216295Ssyrinx
705216295Ssyrinxvoid pp(intptr_t p)          { pp((void*)p); }
706216295Ssyrinxvoid pp(oop p)               { pp((void*)p); }
707216295Ssyrinx
708216295Ssyrinxvoid help() {
709216295Ssyrinx  Command c("help");
710216295Ssyrinx  tty->print_cr("basic");
711216295Ssyrinx  tty->print_cr("  pp(void* p)   - try to make sense of p");
712216295Ssyrinx  tty->print_cr("  pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
713216295Ssyrinx  tty->print_cr("  ps()          - print current thread stack");
714216295Ssyrinx  tty->print_cr("  pss()         - print all thread stacks");
715216295Ssyrinx  tty->print_cr("  pm(int pc)    - print methodOop given compiled PC");
716216295Ssyrinx  tty->print_cr("  findm(intptr_t pc) - finds methodOop");
717216295Ssyrinx  tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
718216295Ssyrinx
719216295Ssyrinx  tty->print_cr("misc.");
720216295Ssyrinx  tty->print_cr("  flush()       - flushes the log file");
721216295Ssyrinx  tty->print_cr("  events()      - dump last 50 events");
722216295Ssyrinx
723216295Ssyrinx
724216295Ssyrinx  tty->print_cr("compiler debugging");
725216295Ssyrinx  tty->print_cr("  debug()       - to set things up for compiler debugging");
726216295Ssyrinx  tty->print_cr("  ndebug()      - undo debug");
727216295Ssyrinx}
728216295Ssyrinx
729216295Ssyrinx#if 0
730216295Ssyrinx
731216295Ssyrinx// BobV's command parser for debugging on windows when nothing else works.
732216295Ssyrinx
733216295Ssyrinxenum CommandID {
734216295Ssyrinx  CMDID_HELP,
735216295Ssyrinx  CMDID_QUIT,
736216295Ssyrinx  CMDID_HSFIND,
737216295Ssyrinx  CMDID_PSS,
738216295Ssyrinx  CMDID_PS,
739216295Ssyrinx  CMDID_PSF,
740216295Ssyrinx  CMDID_FINDM,
741216295Ssyrinx  CMDID_FINDNM,
742216295Ssyrinx  CMDID_PP,
743216295Ssyrinx  CMDID_BPT,
744216295Ssyrinx  CMDID_EXIT,
745216295Ssyrinx  CMDID_VERIFY,
746216295Ssyrinx  CMDID_THREADS,
747216295Ssyrinx  CMDID_ILLEGAL = 99
748311594Sngie};
749216295Ssyrinx
750216295Ssyrinxstruct CommandParser {
751216295Ssyrinx   char *name;
752216295Ssyrinx   CommandID code;
753216295Ssyrinx   char *description;
754216295Ssyrinx};
755216295Ssyrinx
756216295Ssyrinxstruct CommandParser CommandList[] = {
757216295Ssyrinx  (char *)"help", CMDID_HELP, "  Dump this list",
758216295Ssyrinx  (char *)"quit", CMDID_QUIT, "  Return from this routine",
759216295Ssyrinx  (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
760216295Ssyrinx  (char *)"ps", CMDID_PS, "    Print Current Thread Stack Trace",
761216295Ssyrinx  (char *)"pss", CMDID_PSS, "   Print All Thread Stack Trace",
762216295Ssyrinx  (char *)"psf", CMDID_PSF, "   Print All Stack Frames",
763216295Ssyrinx  (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
764216295Ssyrinx  (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
765216295Ssyrinx  (char *)"pp", CMDID_PP, "    Find out something about a pointer",
766216295Ssyrinx  (char *)"break", CMDID_BPT, " Execute a breakpoint",
767216295Ssyrinx  (char *)"exitvm", CMDID_EXIT, "Exit the VM",
768216295Ssyrinx  (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
769216295Ssyrinx  (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
770216295Ssyrinx  (char *)0, CMDID_ILLEGAL
771216295Ssyrinx};
772216295Ssyrinx
773216295Ssyrinx
774216295Ssyrinx// get_debug_command()
775216295Ssyrinx//
776216295Ssyrinx// Read a command from standard input.
777216295Ssyrinx// This is useful when you have a debugger
778216295Ssyrinx// which doesn't support calling into functions.
779216295Ssyrinx//
780216295Ssyrinxvoid get_debug_command()
781216295Ssyrinx{
782216295Ssyrinx  ssize_t count;
783216295Ssyrinx  int i,j;
784216295Ssyrinx  bool gotcommand;
785216295Ssyrinx  intptr_t addr;
786216295Ssyrinx  char buffer[256];
787216295Ssyrinx  nmethod *nm;
788216295Ssyrinx  methodOop m;
789310901Sngie
790216295Ssyrinx  tty->print_cr("You have entered the diagnostic command interpreter");
791216295Ssyrinx  tty->print("The supported commands are:\n");
792216295Ssyrinx  for ( i=0; ; i++ ) {
793216295Ssyrinx    if ( CommandList[i].code == CMDID_ILLEGAL )
794216295Ssyrinx      break;
795216295Ssyrinx    tty->print_cr("  %s \n", CommandList[i].name );
796216295Ssyrinx  }
797216295Ssyrinx
798216295Ssyrinx  while ( 1 ) {
799216295Ssyrinx    gotcommand = false;
800216295Ssyrinx    tty->print("Please enter a command: ");
801216295Ssyrinx    count = scanf("%s", buffer) ;
802216295Ssyrinx    if ( count >=0 ) {
803216295Ssyrinx      for ( i=0; ; i++ ) {
804216295Ssyrinx        if ( CommandList[i].code == CMDID_ILLEGAL ) {
805216295Ssyrinx          if (!gotcommand) tty->print("Invalid command, please try again\n");
806216295Ssyrinx          break;
807216295Ssyrinx        }
808216295Ssyrinx        if ( strcmp(buffer, CommandList[i].name) == 0 ) {
809216295Ssyrinx          gotcommand = true;
810216295Ssyrinx          switch ( CommandList[i].code ) {
811216295Ssyrinx              case CMDID_PS:
812216295Ssyrinx                ps();
813216295Ssyrinx                break;
814216295Ssyrinx              case CMDID_PSS:
815216295Ssyrinx                pss();
816216295Ssyrinx                break;
817216295Ssyrinx              case CMDID_PSF:
818216295Ssyrinx                psf();
819216295Ssyrinx                break;
820216295Ssyrinx              case CMDID_FINDM:
821216295Ssyrinx                tty->print("Please enter the hex addr to pass to findm: ");
822216295Ssyrinx                scanf("%I64X", &addr);
823216295Ssyrinx                m = (methodOop)findm(addr);
824216295Ssyrinx                tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
825216295Ssyrinx                break;
826216295Ssyrinx              case CMDID_FINDNM:
827216295Ssyrinx                tty->print("Please enter the hex addr to pass to findnm: ");
828216295Ssyrinx                scanf("%I64X", &addr);
829216295Ssyrinx                nm = (nmethod*)findnm(addr);
830216295Ssyrinx                tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
831216295Ssyrinx                break;
832216295Ssyrinx              case CMDID_PP:
833311594Sngie                tty->print("Please enter the hex addr to pass to pp: ");
834216295Ssyrinx                scanf("%I64X", &addr);
835216295Ssyrinx                pp((void*)addr);
836216295Ssyrinx                break;
837216295Ssyrinx              case CMDID_EXIT:
838216295Ssyrinx                exit(0);
839216295Ssyrinx              case CMDID_HELP:
840216295Ssyrinx                tty->print("Here are the supported commands: ");
841216295Ssyrinx                for ( j=0; ; j++ ) {
842311594Sngie                  if ( CommandList[j].code == CMDID_ILLEGAL )
843216295Ssyrinx                    break;
844216295Ssyrinx                  tty->print_cr("  %s --  %s\n", CommandList[j].name,
845216295Ssyrinx                                                 CommandList[j].description );
846216295Ssyrinx                }
847216295Ssyrinx                break;
848216295Ssyrinx              case CMDID_QUIT:
849216295Ssyrinx                return;
850216295Ssyrinx                break;
851216295Ssyrinx              case CMDID_BPT:
852216295Ssyrinx                BREAKPOINT;
853311465Sngie                break;
854311465Sngie              case CMDID_VERIFY:
855216295Ssyrinx                verify();;
856216295Ssyrinx                break;
857216295Ssyrinx              case CMDID_THREADS:
858216295Ssyrinx                threads();;
859216295Ssyrinx                break;
860216295Ssyrinx              case CMDID_HSFIND:
861216295Ssyrinx                tty->print("Please enter the hex addr to pass to hsfind: ");
862216295Ssyrinx                scanf("%I64X", &addr);
863216295Ssyrinx                tty->print("Calling hsfind(0x%I64X)\n", addr);
864216295Ssyrinx                hsfind(addr);
865216295Ssyrinx                break;
866216295Ssyrinx              default:
867216295Ssyrinx              case CMDID_ILLEGAL:
868216295Ssyrinx                break;
869216295Ssyrinx          }
870216295Ssyrinx        }
871216295Ssyrinx      }
872216295Ssyrinx    }
873216295Ssyrinx  }
874216295Ssyrinx}
875216295Ssyrinx#endif
876216295Ssyrinx
877216295Ssyrinx#endif // PRODUCT
878216295Ssyrinx