1 /* src/vm/jit/stacktrace.c - machine independent stacktrace system
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
37 #include "mm/gc-common.h"
38 #include "mm/memory.h"
40 #include "vm/jit/stacktrace.h"
42 #include "vm/global.h" /* required here for native includes */
43 #include "native/jni.h"
44 #include "native/llni.h"
46 #include "native/include/java_lang_Object.h"
47 #include "native/include/java_lang_Throwable.h"
49 #if defined(WITH_CLASSPATH_GNU)
50 # include "native/include/gnu_classpath_Pointer.h"
51 # include "native/include/java_lang_VMThrowable.h"
54 #include "threads/thread.h"
56 #include "toolbox/logging.h"
59 #include "vm/builtin.h"
60 #include "vm/cycles-stats.h"
61 #include "vm/exceptions.h"
62 #include "vm/stringlocal.h"
65 #include "vm/jit/asmpart.h"
66 #include "vm/jit/codegen-common.h"
67 #include "vm/jit/linenumbertable.h"
68 #include "vm/jit/methodheader.h"
69 #include "vm/jit/methodtree.h"
71 #include "vmcore/class.h"
72 #include "vmcore/loader.h"
73 #include "vmcore/method.h"
74 #include "vmcore/options.h"
77 /* global variables ***********************************************************/
79 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
80 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
81 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
82 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
83 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
86 /* stacktrace_stackframeinfo_add ***********************************************
88 Fills a stackframe info structure with the given or calculated
89 values and adds it to the chain.
91 *******************************************************************************/
93 void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
95 stackframeinfo_t *currentsfi;
97 #if defined(ENABLE_JIT)
101 /* Get current stackframe info. */
103 currentsfi = threads_get_current_stackframeinfo();
105 /* sometimes we don't have pv handy (e.g. in asmpart.S:
106 L_asm_call_jit_compiler_exception or in the interpreter). */
109 #if defined(ENABLE_INTRP)
111 pv = methodtree_find(ra);
115 #if defined(ENABLE_JIT)
116 # if defined(__SPARC_64__)
117 pv = md_get_pv_from_stackframe(sp);
119 pv = md_codegen_get_pv_from_pc(ra);
125 /* Get codeinfo pointer for the parent Java method. */
127 code = code_get_codeinfo_for_pv(pv);
130 /* assert(m != NULL); */
132 #if defined(ENABLE_JIT)
133 # if defined(ENABLE_INTRP)
134 /* When using the interpreter, we pass RA to the function. */
138 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
139 /* On i386 and x86_64 we always have to get the return address
141 /* m68k has return address on stack always */
142 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
143 the RA from stack. */
145 framesize = *((u4 *) (pv + FrameSize));
147 ra = md_stacktrace_get_returnaddress(sp, framesize);
149 /* If the method is a non-leaf function, we need to get the
150 return address from the stack. For leaf functions the
151 return address is set correctly. This makes the assembler
152 and the signal handler code simpler. The code is NULL is
153 the asm_vm_call_method special case. */
155 if ((code == NULL) || !code_is_leafmethod(code)) {
156 framesize = *((u4 *) (pv + FrameSize));
158 ra = md_stacktrace_get_returnaddress(sp, framesize);
161 # if defined(ENABLE_INTRP)
166 /* Calculate XPC when not given. The XPC is then the return
167 address of the current method minus 1 because the RA points to
168 the instruction after the call instruction. This is required
169 e.g. for method stubs. */
172 xpc = (void *) (((intptr_t) ra) - 1);
175 /* Fill new stackframeinfo structure. */
177 sfi->prev = currentsfi;
185 if (opt_DebugStackFrameInfo) {
187 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
188 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
189 method_print(sfi->code->m);
195 /* Store new stackframeinfo pointer. */
197 threads_set_current_stackframeinfo(sfi);
199 /* set the native world flag for the current thread */
200 /* ATTENTION: This flag tells the GC how to treat this thread in case of
201 a collection. Set this flag _after_ a valid stackframe info was set. */
203 THREAD_NATIVEWORLD_ENTER;
207 /* stacktrace_stackframeinfo_remove ********************************************
209 Remove the given stackframeinfo from the chain in the current
212 *******************************************************************************/
214 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
216 /* Clear the native world flag for the current thread. */
217 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
219 THREAD_NATIVEWORLD_EXIT;
222 if (opt_DebugStackFrameInfo) {
224 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
225 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
226 method_print(sfi->code->m);
232 /* Set previous stackframe info. */
234 threads_set_current_stackframeinfo(sfi->prev);
238 /* stacktrace_stackframeinfo_fill **********************************************
240 Fill the temporary stackframeinfo structure with the values given
244 tmpsfi ... temporary stackframeinfo
245 sfi ...... stackframeinfo to be used in the next iteration
247 *******************************************************************************/
249 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
253 assert(tmpsfi != NULL);
256 /* Fill the temporary stackframeinfo. */
258 tmpsfi->code = sfi->code;
259 tmpsfi->pv = sfi->pv;
260 tmpsfi->sp = sfi->sp;
261 tmpsfi->ra = sfi->ra;
262 tmpsfi->xpc = sfi->xpc;
264 /* Set the previous stackframe info of the temporary one to the
265 next in the chain. */
267 tmpsfi->prev = sfi->prev;
270 if (opt_DebugStackTrace)
271 log_println("[stacktrace fill]");
276 /* stacktrace_stackframeinfo_next **********************************************
278 Walk the stack (or the stackframeinfo-chain) to the next method and
279 return the new stackframe values in the temporary stackframeinfo
282 ATTENTION: This function does NOT skip builtin methods!
285 tmpsfi ... temporary stackframeinfo of current method
287 *******************************************************************************/
289 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
297 stackframeinfo_t *prevsfi;
301 assert(tmpsfi != NULL);
303 /* Get values from the stackframeinfo. */
311 /* Get the current stack frame size. */
313 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
315 /* Get the RA of the current stack frame (RA to the parent Java
316 method) if the current method is a non-leaf method. Otherwise
317 the value in the stackframeinfo is correct (from the signal
320 #if defined(ENABLE_JIT)
321 # if defined(ENABLE_INTRP)
323 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
327 if (!code_is_leafmethod(code))
328 ra = md_stacktrace_get_returnaddress(sp, framesize);
331 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
334 /* Get the PV for the parent Java method. */
336 #if defined(ENABLE_INTRP)
338 pv = methodtree_find(ra);
342 #if defined(ENABLE_JIT)
343 # if defined(__SPARC_64__)
344 sp = md_get_framepointer(sp);
345 pv = md_get_pv_from_stackframe(sp);
347 pv = md_codegen_get_pv_from_pc(ra);
352 /* Get the codeinfo pointer for the parent Java method. */
354 code = code_get_codeinfo_for_pv(pv);
356 /* Calculate the SP for the parent Java method. */
358 #if defined(ENABLE_INTRP)
360 sp = *(u1 **) (sp - framesize);
364 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
365 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
366 #elif defined(__SPARC_64__)
367 /* already has the new sp */
369 sp = (void *) (((intptr_t) sp) + framesize);
373 /* If the new codeinfo pointer is NULL we reached a
374 asm_vm_call_method function. In this case we get the next
375 values from the previous stackframeinfo in the chain.
376 Otherwise the new values have been calculated before. */
379 prevsfi = tmpsfi->prev;
381 /* If the previous stackframeinfo in the chain is NULL we
382 reached the top of the stacktrace. We set code and prev to
383 NULL to mark the end, which is checked in
384 stacktrace_stackframeinfo_end_check. */
386 if (prevsfi == NULL) {
392 /* Fill the temporary stackframeinfo with the new values. */
394 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
397 /* Store the new values in the stackframeinfo. NOTE: We
398 subtract 1 from the RA to get the XPC, because the RA
399 points to the instruction after the call instruction. */
405 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
409 /* Print current method information. */
411 if (opt_DebugStackTrace) {
413 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
414 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
416 method_print(tmpsfi->code->m);
424 /* stacktrace_stackframeinfo_end_check *****************************************
426 Check if we reached the end of the stacktrace.
429 tmpsfi ... temporary stackframeinfo of current method
432 true .... the end is reached
433 false ... the end is not reached
435 *******************************************************************************/
437 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
441 assert(tmpsfi != NULL);
443 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
445 if (opt_DebugStackTrace)
446 log_println("[stacktrace stop]");
456 /* stacktrace_depth ************************************************************
458 Calculates and returns the depth of the current stacktrace.
461 sfi ... stackframeinfo where to start the stacktrace
464 depth of the stacktrace
466 *******************************************************************************/
468 static int stacktrace_depth(stackframeinfo_t *sfi)
470 stackframeinfo_t tmpsfi;
475 if (opt_DebugStackTrace)
476 log_println("[stacktrace_depth]");
479 /* XXX This is not correct, but a workaround for threads-dump for
481 /* assert(sfi != NULL); */
485 /* Iterate over all stackframes. */
489 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
490 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
491 stacktrace_stackframeinfo_next(&tmpsfi)) {
492 /* Get methodinfo. */
496 /* Skip builtin methods. */
498 if (m->flags & ACC_METHOD_BUILTIN)
508 /* stacktrace_get **************************************************************
510 Builds and returns a stacktrace starting from the given stackframe
511 info and returns the stacktrace structure wrapped in a Java
512 byte-array to not confuse the GC.
515 sfi ... stackframe info to start stacktrace from
518 stacktrace as Java byte-array
520 *******************************************************************************/
522 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
524 stackframeinfo_t tmpsfi;
526 java_handle_bytearray_t *ba;
529 stacktrace_entry_t *ste;
531 bool skip_fillInStackTrace;
534 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
537 if (opt_DebugStackTrace)
538 log_println("[stacktrace_get]");
541 skip_fillInStackTrace = true;
544 depth = stacktrace_depth(sfi);
549 /* Allocate memory from the GC heap and copy the stacktrace
551 /* ATTENTION: Use a Java byte-array for this to not confuse the
553 /* FIXME: We waste some memory here as we skip some entries
556 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
558 ba = builtin_newarray_byte(ba_size);
563 /* Get a stacktrace entry pointer. */
564 /* ATTENTION: We need a critical section here because we use the
565 byte-array data pointer directly. */
569 st = (stacktrace_t *) LLNI_array_data(ba);
573 /* Iterate over the whole stack. */
575 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
576 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
577 stacktrace_stackframeinfo_next(&tmpsfi)) {
578 /* Get the methodinfo. */
582 /* Skip builtin methods. */
584 if (m->flags & ACC_METHOD_BUILTIN)
587 /* This logic is taken from
588 hotspot/src/share/vm/classfile/javaClasses.cpp
589 (java_lang_Throwable::fill_in_stack_trace). */
591 if (skip_fillInStackTrace == true) {
592 /* Check "fillInStackTrace" only once, so we negate the
593 flag after the first time check. */
595 #if defined(WITH_CLASSPATH_GNU)
596 /* For GNU Classpath we also need to skip
597 VMThrowable.fillInStackTrace(). */
599 if ((m->clazz == class_java_lang_VMThrowable) &&
600 (m->name == utf_fillInStackTrace))
604 skip_fillInStackTrace = false;
606 if (m->name == utf_fillInStackTrace)
610 /* Skip <init> methods of the exceptions klass. If there is
611 <init> methods that belongs to a superclass of the
612 exception we are going to skipping them in stack trace. */
614 if (skip_init == true) {
615 if ((m->name == utf_init) &&
616 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
620 /* If no "Throwable.init()" method found, we stop
621 checking it next time. */
627 /* Store the stacktrace entry and increment the pointer. */
629 ste->code = tmpsfi.code;
630 ste->pc = tmpsfi.xpc;
635 /* Store the number of entries in the stacktrace structure. */
637 st->length = ste - st->entries;
641 /* release dump memory */
643 /* dump_release(dumpsize); */
645 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
650 /* dump_release(dumpsize); */
652 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
659 /* stacktrace_get_current ******************************************************
661 Builds and returns a stacktrace from the current thread and returns
662 the stacktrace structure wrapped in a Java byte-array to not
666 stacktrace as Java byte-array
668 *******************************************************************************/
670 java_handle_bytearray_t *stacktrace_get_current(void)
672 stackframeinfo_t *sfi;
673 java_handle_bytearray_t *ba;
675 sfi = threads_get_current_stackframeinfo();
676 ba = stacktrace_get(sfi);
682 /* stacktrace_get_caller_class *************************************************
684 Get the class on the stack at the given depth. This function skips
685 various special classes or methods.
688 depth ... depth to get caller class of
693 *******************************************************************************/
695 #if defined(ENABLE_JAVASE)
696 classinfo *stacktrace_get_caller_class(int depth)
698 stackframeinfo_t *sfi;
699 stackframeinfo_t tmpsfi;
705 if (opt_DebugStackTrace)
706 log_println("[stacktrace_get_caller_class]");
709 /* Get the stackframeinfo of the current thread. */
711 sfi = threads_get_current_stackframeinfo();
713 /* Iterate over the whole stack until we reached the requested
718 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
719 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
720 stacktrace_stackframeinfo_next(&tmpsfi)) {
725 /* Skip builtin methods. */
727 if (m->flags & ACC_METHOD_BUILTIN)
730 #if defined(WITH_CLASSPATH_SUN)
731 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
732 (vframeStreamCommon::security_get_caller_frame). */
734 /* This is java.lang.reflect.Method.invoke(), skip it. */
736 if (m == method_java_lang_reflect_Method_invoke)
739 /* This is an auxiliary frame, skip it. */
741 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
745 /* We reached the requested depth. */
758 /* stacktrace_first_nonnull_classloader ****************************************
760 Returns the first non-null (user-defined) classloader on the stack.
761 If none is found NULL is returned.
766 *******************************************************************************/
768 classloader_t *stacktrace_first_nonnull_classloader(void)
770 stackframeinfo_t *sfi;
771 stackframeinfo_t tmpsfi;
776 if (opt_DebugStackTrace)
777 log_println("[stacktrace_first_nonnull_classloader]");
780 /* Get the stackframeinfo of the current thread. */
782 sfi = threads_get_current_stackframeinfo();
784 /* Iterate over the whole stack. */
786 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
787 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
788 stacktrace_stackframeinfo_next(&tmpsfi)) {
791 cl = class_get_classloader(m->clazz);
801 /* stacktrace_getClassContext **************************************************
803 Creates a Class context array.
806 the array of java.lang.Class objects, or
807 NULL if an exception has been thrown
809 *******************************************************************************/
811 java_handle_objectarray_t *stacktrace_getClassContext(void)
813 stackframeinfo_t *sfi;
814 stackframeinfo_t tmpsfi;
816 java_handle_objectarray_t *oa;
817 java_object_t **data;
821 CYCLES_STATS_DECLARE_AND_START
824 if (opt_DebugStackTrace)
825 log_println("[stacktrace_getClassContext]");
828 sfi = threads_get_current_stackframeinfo();
830 /* Get the depth of the current stack. */
832 depth = stacktrace_depth(sfi);
834 /* The first stackframe corresponds to the method whose
835 implementation calls this native function. We remove that
839 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
840 stacktrace_stackframeinfo_next(&tmpsfi);
842 /* Allocate the Class array. */
844 oa = builtin_anewarray(depth, class_java_lang_Class);
847 CYCLES_STATS_END(stacktrace_getClassContext);
852 /* Fill the Class array from the stacktrace list. */
856 data = LLNI_array_data(oa);
858 /* Iterate over the whole stack. */
863 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
864 stacktrace_stackframeinfo_next(&tmpsfi)) {
865 /* Get methodinfo. */
869 /* Skip builtin methods. */
871 if (m->flags & ACC_METHOD_BUILTIN)
874 /* Store the class in the array. */
876 data[i] = (java_object_t *) m->clazz;
883 CYCLES_STATS_END(stacktrace_getClassContext)
889 /* stacktrace_getCurrentClass **************************************************
891 Find the current class by walking the stack trace.
893 Quote from the JNI documentation:
895 In the Java 2 Platform, FindClass locates the class loader
896 associated with the current native method. If the native code
897 belongs to a system class, no class loader will be
898 involved. Otherwise, the proper class loader will be invoked to
899 load and link the named class. When FindClass is called through the
900 Invocation Interface, there is no current native method or its
901 associated class loader. In that case, the result of
902 ClassLoader.getBaseClassLoader is used."
904 *******************************************************************************/
906 #if defined(ENABLE_JAVASE)
907 classinfo *stacktrace_get_current_class(void)
909 stackframeinfo_t *sfi;
910 stackframeinfo_t tmpsfi;
913 CYCLES_STATS_DECLARE_AND_START;
916 if (opt_DebugStackTrace)
917 log_println("[stacktrace_get_current_class]");
920 /* Get the stackframeinfo of the current thread. */
922 sfi = threads_get_current_stackframeinfo();
924 /* If the stackframeinfo is NULL then FindClass is called through
925 the Invocation Interface and we return NULL */
928 CYCLES_STATS_END(stacktrace_getCurrentClass);
933 /* Iterate over the whole stack. */
935 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
936 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
937 stacktrace_stackframeinfo_next(&tmpsfi)) {
938 /* Get the methodinfo. */
942 if (m->clazz == class_java_security_PrivilegedAction) {
943 CYCLES_STATS_END(stacktrace_getCurrentClass);
948 if (m->clazz != NULL) {
949 CYCLES_STATS_END(stacktrace_getCurrentClass);
955 /* No Java method found on the stack. */
957 CYCLES_STATS_END(stacktrace_getCurrentClass);
961 #endif /* ENABLE_JAVASE */
964 /* stacktrace_get_stack ********************************************************
966 Create a 2-dimensional array for java.security.VMAccessControler.
970 NULL if an exception has been thrown
972 *******************************************************************************/
974 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
975 java_handle_objectarray_t *stacktrace_get_stack(void)
977 stackframeinfo_t *sfi;
978 stackframeinfo_t tmpsfi;
980 java_handle_objectarray_t *oa;
981 java_handle_objectarray_t *classes;
982 java_handle_objectarray_t *methodnames;
984 java_handle_t *string;
987 CYCLES_STATS_DECLARE_AND_START
990 if (opt_DebugStackTrace)
991 log_println("[stacktrace_get_stack]");
994 /* Get the stackframeinfo of the current thread. */
996 sfi = threads_get_current_stackframeinfo();
998 /* Get the depth of the current stack. */
1000 depth = stacktrace_depth(sfi);
1005 /* Allocate the required arrays. */
1007 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1012 classes = builtin_anewarray(depth, class_java_lang_Class);
1014 if (classes == NULL)
1017 methodnames = builtin_anewarray(depth, class_java_lang_String);
1019 if (methodnames == NULL)
1022 /* Set up the 2-dimensional array. */
1024 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1025 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1027 /* Iterate over the whole stack. */
1028 /* TODO We should use a critical section here to speed things
1033 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1034 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1035 stacktrace_stackframeinfo_next(&tmpsfi)) {
1036 /* Get the methodinfo. */
1040 /* Skip builtin methods. */
1042 if (m->flags & ACC_METHOD_BUILTIN)
1045 /* Store the class in the array. */
1046 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1049 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1051 /* Store the name in the array. */
1053 string = javastring_new(m->name);
1058 array_objectarray_element_set(methodnames, i, string);
1063 CYCLES_STATS_END(stacktrace_get_stack)
1068 CYCLES_STATS_END(stacktrace_get_stack)
1075 /* stacktrace_print_entry ****************************************************
1077 Print line for a stacktrace entry.
1080 m ............ methodinfo of the entry
1081 linenumber ... linenumber of the entry
1083 *******************************************************************************/
1085 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1093 if (m->flags & ACC_METHOD_BUILTIN)
1096 utf_display_printable_ascii_classname(m->clazz->name);
1099 utf_display_printable_ascii(m->name);
1100 utf_display_printable_ascii(m->descriptor);
1102 if (m->flags & ACC_NATIVE) {
1103 puts("(Native Method)");
1106 if (m->flags & ACC_METHOD_BUILTIN) {
1111 utf_display_printable_ascii(m->clazz->sourcefile);
1112 printf(":%d)\n", linenumber);
1120 /* stacktrace_print ************************************************************
1122 Print the given stacktrace with CACAO intern methods only (no Java
1125 This method is used by stacktrace_dump_trace and
1126 builtin_trace_exception.
1129 st ... stacktrace to print
1131 *******************************************************************************/
1133 void stacktrace_print(stacktrace_t *st)
1135 stacktrace_entry_t *ste;
1140 ste = &(st->entries[0]);
1142 for (i = 0; i < st->length; i++, ste++) {
1145 /* Get the line number. */
1147 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1149 stacktrace_print_entry(m, linenumber);
1154 /* stacktrace_print_current ****************************************************
1156 Print the current stacktrace of the current thread.
1158 NOTE: This function prints all frames of the stacktrace and does
1159 not skip frames like stacktrace_get.
1161 *******************************************************************************/
1163 void stacktrace_print_current(void)
1165 stackframeinfo_t *sfi;
1166 stackframeinfo_t tmpsfi;
1171 sfi = threads_get_current_stackframeinfo();
1174 puts("\t<<No stacktrace available>>");
1179 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1180 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1181 stacktrace_stackframeinfo_next(&tmpsfi)) {
1182 /* Get the methodinfo. */
1187 /* Get the line number. */
1189 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1191 stacktrace_print_entry(m, linenumber);
1196 /* stacktrace_print_of_thread **************************************************
1198 Print the current stacktrace of the given thread.
1203 *******************************************************************************/
1205 #if defined(ENABLE_THREADS)
1206 void stacktrace_print_of_thread(threadobject *t)
1208 stackframeinfo_t *sfi;
1209 stackframeinfo_t tmpsfi;
1214 /* Build a stacktrace for the passed thread. */
1216 sfi = t->_stackframeinfo;
1219 puts("\t<<No stacktrace available>>");
1224 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1225 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1226 stacktrace_stackframeinfo_next(&tmpsfi)) {
1227 /* Get the methodinfo. */
1232 /* Get the line number. */
1234 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1236 stacktrace_print_entry(m, linenumber);
1242 /* stacktrace_print_exception **************************************************
1244 Print the stacktrace of a given exception (more or less a wrapper
1245 to stacktrace_print).
1248 h ... handle of exception to print
1250 *******************************************************************************/
1252 void stacktrace_print_exception(java_handle_t *h)
1254 java_lang_Throwable *o;
1256 #if defined(WITH_CLASSPATH_GNU)
1257 java_lang_VMThrowable *vmt;
1260 java_lang_Object *backtrace;
1261 java_handle_bytearray_t *ba;
1264 o = (java_lang_Throwable *) h;
1269 /* now print the stacktrace */
1271 #if defined(WITH_CLASSPATH_GNU)
1273 LLNI_field_get_ref(o, vmState, vmt);
1274 LLNI_field_get_ref(vmt, vmdata, backtrace);
1276 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1278 LLNI_field_get_ref(o, backtrace, backtrace);
1281 # error unknown classpath configuration
1284 ba = (java_handle_bytearray_t *) backtrace;
1290 /* We need a critical section here as we use the byte-array data
1291 pointer directly. */
1293 LLNI_CRITICAL_START;
1295 st = (stacktrace_t *) LLNI_array_data(ba);
1297 stacktrace_print(st);
1303 #if defined(ENABLE_CYCLES_STATS)
1304 void stacktrace_print_cycles_stats(FILE *file)
1306 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1307 CYCLES_STATS_PRINT(stacktrace_get, file);
1308 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1309 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1310 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1316 * These are local overrides for various environment variables in Emacs.
1317 * Please do not remove this and leave it at the end of the file, where
1318 * Emacs will automagically detect them.
1319 * ---------------------------------------------------------------------
1322 * indent-tabs-mode: t
1326 * vim:noexpandtab:sw=4:ts=4: