Wed, 02 Jan 2013 11:32:41 -0800
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(®_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, ®_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