aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "classfile/systemDictionary.hpp" aoqi@0: #include "code/codeCache.hpp" aoqi@0: #include "code/icBuffer.hpp" aoqi@0: #include "code/nmethod.hpp" aoqi@0: #include "code/vtableStubs.hpp" aoqi@0: #include "compiler/compileBroker.hpp" aoqi@0: #include "compiler/disassembler.hpp" aoqi@0: #include "gc_implementation/shared/markSweep.hpp" aoqi@0: #include "gc_interface/collectedHeap.hpp" aoqi@0: #include "interpreter/bytecodeHistogram.hpp" aoqi@0: #include "interpreter/interpreter.hpp" aoqi@0: #include "memory/resourceArea.hpp" aoqi@0: #include "memory/universe.hpp" aoqi@0: #include "oops/oop.inline.hpp" aoqi@0: #include "prims/privilegedStack.hpp" aoqi@0: #include "runtime/arguments.hpp" aoqi@0: #include "runtime/frame.hpp" aoqi@0: #include "runtime/java.hpp" aoqi@0: #include "runtime/sharedRuntime.hpp" aoqi@0: #include "runtime/stubCodeGenerator.hpp" aoqi@0: #include "runtime/stubRoutines.hpp" aoqi@0: #include "runtime/thread.inline.hpp" aoqi@0: #include "runtime/vframe.hpp" aoqi@0: #include "services/heapDumper.hpp" aoqi@0: #include "utilities/defaultStream.hpp" aoqi@0: #include "utilities/events.hpp" aoqi@0: #include "utilities/top.hpp" aoqi@0: #include "utilities/vmError.hpp" aoqi@0: #ifdef TARGET_OS_FAMILY_linux aoqi@0: # include "os_linux.inline.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_OS_FAMILY_solaris aoqi@0: # include "os_solaris.inline.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_OS_FAMILY_windows aoqi@0: # include "os_windows.inline.hpp" aoqi@0: #endif aoqi@0: #ifdef TARGET_OS_FAMILY_bsd aoqi@0: # include "os_bsd.inline.hpp" aoqi@0: #endif aoqi@0: aoqi@0: #ifndef ASSERT aoqi@0: # ifdef _DEBUG aoqi@0: // NOTE: don't turn the lines below into a comment -- if you're getting aoqi@0: // a compile error here, change the settings to define ASSERT aoqi@0: ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging aoqi@0: functions that do not slow down the system too much and thus can be left in optimized code. aoqi@0: On the other hand, the code should not be included in a production version. aoqi@0: # endif // _DEBUG aoqi@0: #endif // ASSERT aoqi@0: aoqi@0: aoqi@0: #ifdef _DEBUG aoqi@0: # ifndef ASSERT aoqi@0: configuration error: ASSERT must be defined in debug version aoqi@0: # endif // ASSERT aoqi@0: #endif // _DEBUG aoqi@0: aoqi@0: aoqi@0: #ifdef PRODUCT aoqi@0: # if -defined _DEBUG || -defined ASSERT aoqi@0: configuration error: ASSERT et al. must not be defined in PRODUCT version aoqi@0: # endif aoqi@0: #endif // PRODUCT aoqi@0: aoqi@0: PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC aoqi@0: aoqi@0: FormatBufferResource::FormatBufferResource(const char * format, ...) aoqi@0: : FormatBufferBase((char*)resource_allocate_bytes(RES_BUFSZ)) { aoqi@0: va_list argp; aoqi@0: va_start(argp, format); aoqi@0: jio_vsnprintf(_buf, RES_BUFSZ, format, argp); aoqi@0: va_end(argp); aoqi@0: } aoqi@0: aoqi@0: ATTRIBUTE_PRINTF(1, 2) aoqi@0: void warning(const char* format, ...) { aoqi@0: if (PrintWarnings) { aoqi@0: FILE* const err = defaultStream::error_stream(); aoqi@0: jio_fprintf(err, "%s warning: ", VM_Version::vm_name()); aoqi@0: va_list ap; aoqi@0: va_start(ap, format); aoqi@0: vfprintf(err, format, ap); aoqi@0: va_end(ap); aoqi@0: fputc('\n', err); aoqi@0: } aoqi@0: if (BreakAtWarning) BREAKPOINT; aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: #define is_token_break(ch) (isspace(ch) || (ch) == ',') aoqi@0: aoqi@0: static const char* last_file_name = NULL; aoqi@0: static int last_line_no = -1; aoqi@0: aoqi@0: // assert/guarantee/... may happen very early during VM initialization. aoqi@0: // Don't rely on anything that is initialized by Threads::create_vm(). For aoqi@0: // example, don't use tty. aoqi@0: bool error_is_suppressed(const char* file_name, int line_no) { aoqi@0: // The following 1-element cache requires that passed-in aoqi@0: // file names are always only constant literals. aoqi@0: if (file_name == last_file_name && line_no == last_line_no) return true; aoqi@0: aoqi@0: int file_name_len = (int)strlen(file_name); aoqi@0: char separator = os::file_separator()[0]; aoqi@0: const char* base_name = strrchr(file_name, separator); aoqi@0: if (base_name == NULL) aoqi@0: base_name = file_name; aoqi@0: aoqi@0: // scan the SuppressErrorAt option aoqi@0: const char* cp = SuppressErrorAt; aoqi@0: for (;;) { aoqi@0: const char* sfile; aoqi@0: int sfile_len; aoqi@0: int sline; aoqi@0: bool noisy; aoqi@0: while ((*cp) != '\0' && is_token_break(*cp)) cp++; aoqi@0: if ((*cp) == '\0') break; aoqi@0: sfile = cp; aoqi@0: while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; aoqi@0: sfile_len = cp - sfile; aoqi@0: if ((*cp) == ':') cp++; aoqi@0: sline = 0; aoqi@0: while ((*cp) != '\0' && isdigit(*cp)) { aoqi@0: sline *= 10; aoqi@0: sline += (*cp) - '0'; aoqi@0: cp++; aoqi@0: } aoqi@0: // "file:line!" means the assert suppression is not silent aoqi@0: noisy = ((*cp) == '!'); aoqi@0: while ((*cp) != '\0' && !is_token_break(*cp)) cp++; aoqi@0: // match the line aoqi@0: if (sline != 0) { aoqi@0: if (sline != line_no) continue; aoqi@0: } aoqi@0: // match the file aoqi@0: if (sfile_len > 0) { aoqi@0: const char* look = file_name; aoqi@0: const char* look_max = file_name + file_name_len - sfile_len; aoqi@0: const char* foundp; aoqi@0: bool match = false; aoqi@0: while (!match aoqi@0: && (foundp = strchr(look, sfile[0])) != NULL aoqi@0: && foundp <= look_max) { aoqi@0: match = true; aoqi@0: for (int i = 1; i < sfile_len; i++) { aoqi@0: if (sfile[i] != foundp[i]) { aoqi@0: match = false; aoqi@0: break; aoqi@0: } aoqi@0: } aoqi@0: look = foundp + 1; aoqi@0: } aoqi@0: if (!match) continue; aoqi@0: } aoqi@0: // got a match! aoqi@0: if (noisy) { aoqi@0: fdStream out(defaultStream::output_fd()); aoqi@0: out.print_raw("[error suppressed at "); aoqi@0: out.print_raw(base_name); aoqi@0: char buf[16]; aoqi@0: jio_snprintf(buf, sizeof(buf), ":%d]", line_no); aoqi@0: out.print_raw_cr(buf); aoqi@0: } else { aoqi@0: // update 1-element cache for fast silent matches aoqi@0: last_file_name = file_name; aoqi@0: last_line_no = line_no; aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: if (!is_error_reported()) { aoqi@0: // print a friendly hint: aoqi@0: fdStream out(defaultStream::output_fd()); aoqi@0: out.print_raw_cr("# To suppress the following error report, specify this argument"); aoqi@0: out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); aoqi@0: out.print_raw (base_name); aoqi@0: char buf[16]; aoqi@0: jio_snprintf(buf, sizeof(buf), ":%d", line_no); aoqi@0: out.print_raw_cr(buf); aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: #undef is_token_break aoqi@0: aoqi@0: #else aoqi@0: aoqi@0: // Place-holder for non-existent suppression check: aoqi@0: #define error_is_suppressed(file_name, line_no) (false) aoqi@0: aoqi@0: #endif // !PRODUCT aoqi@0: aoqi@0: void report_vm_error(const char* file, int line, const char* error_msg, aoqi@0: const char* detail_msg) aoqi@0: { aoqi@0: if (Debugging || error_is_suppressed(file, line)) return; aoqi@0: Thread* const thread = ThreadLocalStorage::get_thread_slow(); aoqi@0: VMError err(thread, file, line, error_msg, detail_msg); aoqi@0: err.report_and_die(); aoqi@0: } aoqi@0: aoqi@0: void report_fatal(const char* file, int line, const char* message) aoqi@0: { aoqi@0: report_vm_error(file, line, "fatal error", message); aoqi@0: } aoqi@0: aoqi@0: void report_vm_out_of_memory(const char* file, int line, size_t size, aoqi@0: VMErrorType vm_err_type, const char* message) { aoqi@0: if (Debugging) return; aoqi@0: aoqi@0: Thread* thread = ThreadLocalStorage::get_thread_slow(); aoqi@0: VMError(thread, file, line, size, vm_err_type, message).report_and_die(); aoqi@0: aoqi@0: // The UseOSErrorReporting option in report_and_die() may allow a return aoqi@0: // to here. If so then we'll have to figure out how to handle it. aoqi@0: guarantee(false, "report_and_die() should not return here"); aoqi@0: } aoqi@0: aoqi@0: void report_should_not_call(const char* file, int line) { aoqi@0: report_vm_error(file, line, "ShouldNotCall()"); aoqi@0: } aoqi@0: aoqi@0: void report_should_not_reach_here(const char* file, int line) { aoqi@0: report_vm_error(file, line, "ShouldNotReachHere()"); aoqi@0: } aoqi@0: aoqi@0: void report_unimplemented(const char* file, int line) { aoqi@0: report_vm_error(file, line, "Unimplemented()"); aoqi@0: } aoqi@0: aoqi@0: void report_untested(const char* file, int line, const char* message) { aoqi@0: #ifndef PRODUCT aoqi@0: warning("Untested: %s in %s: %d\n", message, file, line); aoqi@0: #endif // !PRODUCT aoqi@0: } aoqi@0: aoqi@0: void report_out_of_shared_space(SharedSpaceType shared_space) { aoqi@0: static const char* name[] = { aoqi@0: "native memory for metadata", aoqi@0: "shared read only space", aoqi@0: "shared read write space", ccheung@7300: "shared miscellaneous data space", ccheung@7300: "shared miscellaneous code space" aoqi@0: }; aoqi@0: static const char* flag[] = { aoqi@0: "Metaspace", aoqi@0: "SharedReadOnlySize", aoqi@0: "SharedReadWriteSize", ccheung@7300: "SharedMiscDataSize", ccheung@7300: "SharedMiscCodeSize" aoqi@0: }; aoqi@0: aoqi@0: warning("\nThe %s is not large enough\n" ccheung@7300: "to preload requested classes. Use -XX:%s=\n" aoqi@0: "to increase the initial size of %s.\n", aoqi@0: name[shared_space], flag[shared_space], name[shared_space]); aoqi@0: exit(2); aoqi@0: } aoqi@0: aoqi@0: void report_java_out_of_memory(const char* message) { aoqi@0: static jint out_of_memory_reported = 0; aoqi@0: aoqi@0: // A number of threads may attempt to report OutOfMemoryError at around the aoqi@0: // same time. To avoid dumping the heap or executing the data collection aoqi@0: // commands multiple times we just do it once when the first threads reports aoqi@0: // the error. aoqi@0: if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { aoqi@0: // create heap dump before OnOutOfMemoryError commands are executed aoqi@0: if (HeapDumpOnOutOfMemoryError) { aoqi@0: tty->print_cr("java.lang.OutOfMemoryError: %s", message); aoqi@0: HeapDumper::dump_heap_from_oome(); aoqi@0: } aoqi@0: aoqi@0: if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { aoqi@0: VMError err(message); aoqi@0: err.report_java_out_of_memory(); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static bool error_reported = false; aoqi@0: aoqi@0: // call this when the VM is dying--it might loosen some asserts aoqi@0: void set_error_reported() { aoqi@0: error_reported = true; aoqi@0: } aoqi@0: aoqi@0: bool is_error_reported() { aoqi@0: return error_reported; aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: #include aoqi@0: aoqi@0: void test_error_handler() { aoqi@0: uintx test_num = ErrorHandlerTest; aoqi@0: if (test_num == 0) return; aoqi@0: aoqi@0: // If asserts are disabled, use the corresponding guarantee instead. aoqi@0: size_t n = test_num; aoqi@0: NOT_DEBUG(if (n <= 2) n += 2); aoqi@0: aoqi@0: const char* const str = "hello"; aoqi@0: const size_t num = (size_t)os::vm_page_size(); aoqi@0: aoqi@0: const char* const eol = os::line_separator(); aoqi@0: const char* const msg = "this message should be truncated during formatting"; aoqi@0: char * const dataPtr = NULL; // bad data pointer aoqi@0: const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer aoqi@0: aoqi@0: // Keep this in sync with test/runtime/6888954/vmerrors.sh. aoqi@0: switch (n) { aoqi@0: case 1: assert(str == NULL, "expected null"); aoqi@0: case 2: assert(num == 1023 && *str == 'X', aoqi@0: err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); aoqi@0: case 3: guarantee(str == NULL, "expected null"); aoqi@0: case 4: guarantee(num == 1023 && *str == 'X', aoqi@0: err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); aoqi@0: case 5: fatal("expected null"); aoqi@0: case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); aoqi@0: case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " aoqi@0: "%s%s# %s%s# %s%s# %s%s# %s%s# " aoqi@0: "%s%s# %s%s# %s%s# %s%s# %s", aoqi@0: msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, aoqi@0: msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, aoqi@0: msg, eol, msg, eol, msg, eol, msg, eol, msg)); aoqi@0: case 8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate"); aoqi@0: case 9: ShouldNotCallThis(); aoqi@0: case 10: ShouldNotReachHere(); aoqi@0: case 11: Unimplemented(); aoqi@0: // There's no guarantee the bad data pointer will crash us aoqi@0: // so "break" out to the ShouldNotReachHere(). aoqi@0: case 12: *dataPtr = '\0'; break; aoqi@0: // There's no guarantee the bad function pointer will crash us aoqi@0: // so "break" out to the ShouldNotReachHere(). aoqi@0: case 13: (*funcPtr)(); break; aoqi@0: aoqi@0: default: tty->print_cr("ERROR: %d: unexpected test_num value.", n); aoqi@0: } aoqi@0: ShouldNotReachHere(); aoqi@0: } aoqi@0: #endif // !PRODUCT aoqi@0: aoqi@0: // ------ helper functions for debugging go here ------------ aoqi@0: aoqi@0: // All debug entries should be wrapped with a stack allocated aoqi@0: // Command object. It makes sure a resource mark is set and aoqi@0: // flushes the logfile to prevent file sharing problems. aoqi@0: aoqi@0: class Command : public StackObj { aoqi@0: private: aoqi@0: ResourceMark rm; aoqi@0: ResetNoHandleMark rnhm; aoqi@0: HandleMark hm; aoqi@0: bool debug_save; aoqi@0: public: aoqi@0: static int level; aoqi@0: Command(const char* str) { aoqi@0: debug_save = Debugging; aoqi@0: Debugging = true; aoqi@0: if (level++ > 0) return; aoqi@0: tty->cr(); aoqi@0: tty->print_cr("\"Executing %s\"", str); aoqi@0: } aoqi@0: aoqi@0: ~Command() { aoqi@0: tty->flush(); aoqi@0: Debugging = debug_save; aoqi@0: level--; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: int Command::level = 0; aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: extern "C" void blob(CodeBlob* cb) { aoqi@0: Command c("blob"); aoqi@0: cb->print(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void dump_vtable(address p) { aoqi@0: Command c("dump_vtable"); aoqi@0: Klass* k = (Klass*)p; aoqi@0: InstanceKlass::cast(k)->vtable()->print(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void nm(intptr_t p) { aoqi@0: // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) aoqi@0: Command c("nm"); aoqi@0: CodeBlob* cb = CodeCache::find_blob((address)p); aoqi@0: if (cb == NULL) { aoqi@0: tty->print_cr("NULL"); aoqi@0: } else { aoqi@0: cb->print(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void disnm(intptr_t p) { aoqi@0: Command c("disnm"); aoqi@0: CodeBlob* cb = CodeCache::find_blob((address) p); aoqi@0: nmethod* nm = cb->as_nmethod_or_null(); aoqi@0: if (nm) { aoqi@0: nm->print(); aoqi@0: Disassembler::decode(nm); aoqi@0: } else { aoqi@0: cb->print(); aoqi@0: Disassembler::decode(cb); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void printnm(intptr_t p) { aoqi@0: char buffer[256]; aoqi@0: sprintf(buffer, "printnm: " INTPTR_FORMAT, p); aoqi@0: Command c(buffer); aoqi@0: CodeBlob* cb = CodeCache::find_blob((address) p); aoqi@0: if (cb->is_nmethod()) { aoqi@0: nmethod* nm = (nmethod*)cb; aoqi@0: nm->print_nmethod(true); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void universe() { aoqi@0: Command c("universe"); aoqi@0: Universe::print(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void verify() { aoqi@0: // try to run a verify on the entire system aoqi@0: // note: this may not be safe if we're not at a safepoint; for debugging, aoqi@0: // this manipulates the safepoint settings to avoid assertion failures aoqi@0: Command c("universe verify"); aoqi@0: bool safe = SafepointSynchronize::is_at_safepoint(); aoqi@0: if (!safe) { aoqi@0: tty->print_cr("warning: not at safepoint -- verify may fail"); aoqi@0: SafepointSynchronize::set_is_at_safepoint(); aoqi@0: } aoqi@0: // Ensure Eden top is correct before verification aoqi@0: Universe::heap()->prepare_for_verify(); aoqi@0: Universe::verify(); aoqi@0: if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void pp(void* p) { aoqi@0: Command c("pp"); aoqi@0: FlagSetting fl(PrintVMMessages, true); aoqi@0: FlagSetting f2(DisplayVMOutput, true); aoqi@0: if (Universe::heap()->is_in(p)) { aoqi@0: oop obj = oop(p); aoqi@0: obj->print(); aoqi@0: } else { aoqi@0: tty->print(PTR_FORMAT, p); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // pv: print vm-printable object aoqi@0: extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } aoqi@0: extern "C" void findpc(intptr_t x); aoqi@0: aoqi@0: #endif // !PRODUCT aoqi@0: aoqi@0: extern "C" void ps() { // print stack aoqi@0: if (Thread::current() == NULL) return; aoqi@0: Command c("ps"); aoqi@0: aoqi@0: aoqi@0: // Prints the stack of the current Java thread aoqi@0: JavaThread* p = JavaThread::active(); aoqi@0: tty->print(" for thread: "); aoqi@0: p->print(); aoqi@0: tty->cr(); aoqi@0: aoqi@0: if (p->has_last_Java_frame()) { aoqi@0: // If the last_Java_fp is set we are in C land and aoqi@0: // can call the standard stack_trace function. aoqi@0: #ifdef PRODUCT aoqi@0: p->print_stack(); aoqi@0: } else { aoqi@0: tty->print_cr("Cannot find the last Java frame, printing stack disabled."); aoqi@0: #else // !PRODUCT aoqi@0: p->trace_stack(); aoqi@0: } else { aoqi@0: frame f = os::current_frame(); aoqi@0: RegisterMap reg_map(p); aoqi@0: f = f.sender(®_map); aoqi@0: tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); aoqi@0: p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); aoqi@0: pd_ps(f); aoqi@0: #endif // PRODUCT aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: extern "C" void pfl() { aoqi@0: // print frame layout aoqi@0: Command c("pfl"); aoqi@0: JavaThread* p = JavaThread::active(); aoqi@0: tty->print(" for thread: "); aoqi@0: p->print(); aoqi@0: tty->cr(); aoqi@0: if (p->has_last_Java_frame()) { aoqi@0: p->print_frame_layout(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: extern "C" void psf() { // print stack frames aoqi@0: { aoqi@0: Command c("psf"); aoqi@0: JavaThread* p = JavaThread::active(); aoqi@0: tty->print(" for thread: "); aoqi@0: p->print(); aoqi@0: tty->cr(); aoqi@0: if (p->has_last_Java_frame()) { aoqi@0: p->trace_frames(); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void threads() { aoqi@0: Command c("threads"); aoqi@0: Threads::print(false, true); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void psd() { aoqi@0: Command c("psd"); aoqi@0: SystemDictionary::print(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void safepoints() { aoqi@0: Command c("safepoints"); aoqi@0: SafepointSynchronize::print_state(); aoqi@0: } aoqi@0: aoqi@0: #endif // !PRODUCT aoqi@0: aoqi@0: extern "C" void pss() { // print all stacks aoqi@0: if (Thread::current() == NULL) return; aoqi@0: Command c("pss"); aoqi@0: Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true)); aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: extern "C" void debug() { // to set things up for compiler debugging aoqi@0: Command c("debug"); aoqi@0: WizardMode = true; aoqi@0: PrintVMMessages = PrintCompilation = true; aoqi@0: PrintInlining = PrintAssembly = true; aoqi@0: tty->flush(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void ndebug() { // undo debug() aoqi@0: Command c("ndebug"); aoqi@0: PrintCompilation = false; aoqi@0: PrintInlining = PrintAssembly = false; aoqi@0: tty->flush(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void flush() { aoqi@0: Command c("flush"); aoqi@0: tty->flush(); aoqi@0: } aoqi@0: aoqi@0: extern "C" void events() { aoqi@0: Command c("events"); aoqi@0: Events::print(); aoqi@0: } aoqi@0: aoqi@0: extern "C" Method* findm(intptr_t pc) { aoqi@0: Command c("findm"); aoqi@0: nmethod* nm = CodeCache::find_nmethod((address)pc); aoqi@0: return (nm == NULL) ? (Method*)NULL : nm->method(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" nmethod* findnm(intptr_t addr) { aoqi@0: Command c("findnm"); aoqi@0: return CodeCache::find_nmethod((address)addr); aoqi@0: } aoqi@0: aoqi@0: // Another interface that isn't ambiguous in dbx. aoqi@0: // Can we someday rename the other find to hsfind? aoqi@0: extern "C" void hsfind(intptr_t x) { aoqi@0: Command c("hsfind"); aoqi@0: os::print_location(tty, x, false); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void find(intptr_t x) { aoqi@0: Command c("find"); aoqi@0: os::print_location(tty, x, false); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: extern "C" void findpc(intptr_t x) { aoqi@0: Command c("findpc"); aoqi@0: os::print_location(tty, x, true); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // Need method pointer to find bcp, when not in permgen. aoqi@0: extern "C" void findbcp(intptr_t method, intptr_t bcp) { aoqi@0: Command c("findbcp"); aoqi@0: Method* mh = (Method*)method; aoqi@0: if (!mh->is_native()) { aoqi@0: tty->print_cr("bci_from(%p) = %d; print_codes():", aoqi@0: mh, mh->bci_from(address(bcp))); aoqi@0: mh->print_codes_on(tty); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // int versions of all methods to avoid having to type type casts in the debugger aoqi@0: aoqi@0: void pp(intptr_t p) { pp((void*)p); } aoqi@0: void pp(oop p) { pp((void*)p); } aoqi@0: aoqi@0: void help() { aoqi@0: Command c("help"); aoqi@0: tty->print_cr("basic"); aoqi@0: tty->print_cr(" pp(void* p) - try to make sense of p"); aoqi@0: tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); aoqi@0: tty->print_cr(" ps() - print current thread stack"); aoqi@0: tty->print_cr(" pss() - print all thread stacks"); aoqi@0: tty->print_cr(" pm(int pc) - print Method* given compiled PC"); aoqi@0: tty->print_cr(" findm(intptr_t pc) - finds Method*"); aoqi@0: tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); aoqi@0: aoqi@0: tty->print_cr("misc."); aoqi@0: tty->print_cr(" flush() - flushes the log file"); aoqi@0: tty->print_cr(" events() - dump events from ring buffers"); aoqi@0: aoqi@0: aoqi@0: tty->print_cr("compiler debugging"); aoqi@0: tty->print_cr(" debug() - to set things up for compiler debugging"); aoqi@0: tty->print_cr(" ndebug() - undo debug"); aoqi@0: } aoqi@0: aoqi@0: #endif // !PRODUCT