1 /* src/vm/jit/stacktrace.cpp - 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
38 #include "mm/memory.h"
40 #include "vm/jit/stacktrace.hpp"
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_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
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 // FIXME Use C-linkage for now.
80 /* global variables ***********************************************************/
82 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
83 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
84 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
85 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
86 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
87 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
90 /* stacktrace_stackframeinfo_add ***********************************************
92 Fills a stackframe info structure with the given or calculated
93 values and adds it to the chain.
95 *******************************************************************************/
97 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
99 stackframeinfo_t *currentsfi;
101 #if defined(ENABLE_JIT)
105 /* Get current stackframe info. */
107 currentsfi = threads_get_current_stackframeinfo();
109 /* sometimes we don't have pv handy (e.g. in asmpart.S:
110 L_asm_call_jit_compiler_exception or in the interpreter). */
113 #if defined(ENABLE_INTRP)
115 pv = methodtree_find(ra);
119 #if defined(ENABLE_JIT)
120 # if defined(__SPARC_64__)
121 pv = md_get_pv_from_stackframe(sp);
123 pv = md_codegen_get_pv_from_pc(ra);
129 /* Get codeinfo pointer for the parent Java method. */
131 code = code_get_codeinfo_for_pv(pv);
134 /* assert(m != NULL); */
136 #if defined(ENABLE_JIT)
137 # if defined(ENABLE_INTRP)
138 /* When using the interpreter, we pass RA to the function. */
142 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
143 /* On i386 and x86_64 we always have to get the return address
145 /* m68k has return address on stack always */
146 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
147 the RA from stack. */
149 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
151 ra = md_stacktrace_get_returnaddress(sp, framesize);
153 /* If the method is a non-leaf function, we need to get the
154 return address from the stack. For leaf functions the
155 return address is set correctly. This makes the assembler
156 and the signal handler code simpler. The code is NULL is
157 the asm_vm_call_method special case. */
159 if ((code == NULL) || !code_is_leafmethod(code)) {
160 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
162 ra = md_stacktrace_get_returnaddress(sp, framesize);
165 # if defined(ENABLE_INTRP)
170 /* Calculate XPC when not given. The XPC is then the return
171 address of the current method minus 1 because the RA points to
172 the instruction after the call instruction. This is required
173 e.g. for method stubs. */
176 xpc = (void *) (((intptr_t) ra) - 1);
179 /* Fill new stackframeinfo structure. */
181 sfi->prev = currentsfi;
189 if (opt_DebugStackFrameInfo) {
191 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
192 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
193 method_print(sfi->code->m);
199 /* Store new stackframeinfo pointer. */
201 threads_set_current_stackframeinfo(sfi);
203 /* set the native world flag for the current thread */
204 /* ATTENTION: This flag tells the GC how to treat this thread in case of
205 a collection. Set this flag _after_ a valid stackframe info was set. */
207 THREAD_NATIVEWORLD_ENTER;
211 /* stacktrace_stackframeinfo_remove ********************************************
213 Remove the given stackframeinfo from the chain in the current
216 *******************************************************************************/
218 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
220 /* Clear the native world flag for the current thread. */
221 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
223 THREAD_NATIVEWORLD_EXIT;
226 if (opt_DebugStackFrameInfo) {
228 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
229 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
230 method_print(sfi->code->m);
236 /* Set previous stackframe info. */
238 threads_set_current_stackframeinfo(sfi->prev);
242 /* stacktrace_stackframeinfo_fill **********************************************
244 Fill the temporary stackframeinfo structure with the values given
248 tmpsfi ... temporary stackframeinfo
249 sfi ...... stackframeinfo to be used in the next iteration
251 *******************************************************************************/
253 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
257 assert(tmpsfi != NULL);
260 /* Fill the temporary stackframeinfo. */
262 tmpsfi->code = sfi->code;
263 tmpsfi->pv = sfi->pv;
264 tmpsfi->sp = sfi->sp;
265 tmpsfi->ra = sfi->ra;
266 tmpsfi->xpc = sfi->xpc;
268 /* Set the previous stackframe info of the temporary one to the
269 next in the chain. */
271 tmpsfi->prev = sfi->prev;
274 if (opt_DebugStackTrace)
275 log_println("[stacktrace fill]");
280 /* stacktrace_stackframeinfo_next **********************************************
282 Walk the stack (or the stackframeinfo-chain) to the next method and
283 return the new stackframe values in the temporary stackframeinfo
286 ATTENTION: This function does NOT skip builtin methods!
289 tmpsfi ... temporary stackframeinfo of current method
291 *******************************************************************************/
293 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
301 stackframeinfo_t *prevsfi;
305 assert(tmpsfi != NULL);
307 /* Get values from the stackframeinfo. */
315 /* Get the current stack frame size. */
317 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
319 /* Get the RA of the current stack frame (RA to the parent Java
320 method) if the current method is a non-leaf method. Otherwise
321 the value in the stackframeinfo is correct (from the signal
324 #if defined(ENABLE_JIT)
325 # if defined(ENABLE_INTRP)
327 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
331 if (!code_is_leafmethod(code))
332 ra = md_stacktrace_get_returnaddress(sp, framesize);
335 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
338 /* Get the PV for the parent Java method. */
340 #if defined(ENABLE_INTRP)
342 pv = methodtree_find(ra);
346 #if defined(ENABLE_JIT)
347 # if defined(__SPARC_64__)
348 sp = md_get_framepointer(sp);
349 pv = md_get_pv_from_stackframe(sp);
351 pv = md_codegen_get_pv_from_pc(ra);
356 /* Get the codeinfo pointer for the parent Java method. */
358 code = code_get_codeinfo_for_pv(pv);
360 /* Calculate the SP for the parent Java method. */
362 #if defined(ENABLE_INTRP)
364 sp = *(u1 **) (sp - framesize);
368 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
369 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
370 #elif defined(__SPARC_64__)
371 /* already has the new sp */
373 sp = (void *) (((intptr_t) sp) + framesize);
377 /* If the new codeinfo pointer is NULL we reached a
378 asm_vm_call_method function. In this case we get the next
379 values from the previous stackframeinfo in the chain.
380 Otherwise the new values have been calculated before. */
383 prevsfi = tmpsfi->prev;
385 /* If the previous stackframeinfo in the chain is NULL we
386 reached the top of the stacktrace. We set code and prev to
387 NULL to mark the end, which is checked in
388 stacktrace_stackframeinfo_end_check. */
390 if (prevsfi == NULL) {
396 /* Fill the temporary stackframeinfo with the new values. */
398 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
401 /* Store the new values in the stackframeinfo. NOTE: We
402 subtract 1 from the RA to get the XPC, because the RA
403 points to the instruction after the call instruction. */
409 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
413 /* Print current method information. */
415 if (opt_DebugStackTrace) {
417 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
418 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
420 method_print(tmpsfi->code->m);
428 /* stacktrace_stackframeinfo_end_check *****************************************
430 Check if we reached the end of the stacktrace.
433 tmpsfi ... temporary stackframeinfo of current method
436 true .... the end is reached
437 false ... the end is not reached
439 *******************************************************************************/
441 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
445 assert(tmpsfi != NULL);
447 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
449 if (opt_DebugStackTrace)
450 log_println("[stacktrace stop]");
460 /* stacktrace_depth ************************************************************
462 Calculates and returns the depth of the current stacktrace.
465 sfi ... stackframeinfo where to start the stacktrace
468 depth of the stacktrace
470 *******************************************************************************/
472 static int stacktrace_depth(stackframeinfo_t *sfi)
474 stackframeinfo_t tmpsfi;
479 if (opt_DebugStackTrace)
480 log_println("[stacktrace_depth]");
483 /* XXX This is not correct, but a workaround for threads-dump for
485 /* assert(sfi != NULL); */
489 /* Iterate over all stackframes. */
493 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
494 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
495 stacktrace_stackframeinfo_next(&tmpsfi)) {
496 /* Get methodinfo. */
500 /* Skip builtin methods. */
502 if (m->flags & ACC_METHOD_BUILTIN)
512 /* stacktrace_get **************************************************************
514 Builds and returns a stacktrace starting from the given stackframe
515 info and returns the stacktrace structure wrapped in a Java
516 byte-array to not confuse the GC.
519 sfi ... stackframe info to start stacktrace from
522 stacktrace as Java byte-array
524 *******************************************************************************/
526 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
528 stackframeinfo_t tmpsfi;
530 java_handle_bytearray_t *ba;
533 stacktrace_entry_t *ste;
535 bool skip_fillInStackTrace;
538 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
541 if (opt_DebugStackTrace)
542 log_println("[stacktrace_get]");
545 skip_fillInStackTrace = true;
548 depth = stacktrace_depth(sfi);
553 /* Allocate memory from the GC heap and copy the stacktrace
555 /* ATTENTION: Use a Java byte-array for this to not confuse the
557 /* FIXME: We waste some memory here as we skip some entries
560 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
562 ba = builtin_newarray_byte(ba_size);
567 /* Get a stacktrace entry pointer. */
568 /* ATTENTION: We need a critical section here because we use the
569 byte-array data pointer directly. */
573 st = (stacktrace_t *) LLNI_array_data(ba);
577 /* Iterate over the whole stack. */
579 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
580 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
581 stacktrace_stackframeinfo_next(&tmpsfi)) {
582 /* Get the methodinfo. */
586 /* Skip builtin methods. */
588 if (m->flags & ACC_METHOD_BUILTIN)
591 /* This logic is taken from
592 hotspot/src/share/vm/classfile/javaClasses.cpp
593 (java_lang_Throwable::fill_in_stack_trace). */
595 if (skip_fillInStackTrace == true) {
596 /* Check "fillInStackTrace" only once, so we negate the
597 flag after the first time check. */
599 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
600 /* For GNU Classpath we also need to skip
601 VMThrowable.fillInStackTrace(). */
603 if ((m->clazz == class_java_lang_VMThrowable) &&
604 (m->name == utf_fillInStackTrace))
608 skip_fillInStackTrace = false;
610 if (m->name == utf_fillInStackTrace)
614 /* Skip <init> methods of the exceptions klass. If there is
615 <init> methods that belongs to a superclass of the
616 exception we are going to skipping them in stack trace. */
618 if (skip_init == true) {
619 if ((m->name == utf_init) &&
620 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
624 /* If no "Throwable.init()" method found, we stop
625 checking it next time. */
631 /* Store the stacktrace entry and increment the pointer. */
633 ste->code = tmpsfi.code;
634 ste->pc = tmpsfi.xpc;
639 /* Store the number of entries in the stacktrace structure. */
641 st->length = ste - st->entries;
645 /* release dump memory */
647 /* dump_release(dumpsize); */
649 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
654 /* dump_release(dumpsize); */
656 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
663 /* stacktrace_get_current ******************************************************
665 Builds and returns a stacktrace from the current thread and returns
666 the stacktrace structure wrapped in a Java byte-array to not
670 stacktrace as Java byte-array
672 *******************************************************************************/
674 java_handle_bytearray_t *stacktrace_get_current(void)
676 stackframeinfo_t *sfi;
677 java_handle_bytearray_t *ba;
679 sfi = threads_get_current_stackframeinfo();
680 ba = stacktrace_get(sfi);
686 /* stacktrace_get_caller_class *************************************************
688 Get the class on the stack at the given depth. This function skips
689 various special classes or methods.
692 depth ... depth to get caller class of
697 *******************************************************************************/
699 #if defined(ENABLE_JAVASE)
700 classinfo *stacktrace_get_caller_class(int depth)
702 stackframeinfo_t *sfi;
703 stackframeinfo_t tmpsfi;
709 if (opt_DebugStackTrace)
710 log_println("[stacktrace_get_caller_class]");
713 /* Get the stackframeinfo of the current thread. */
715 sfi = threads_get_current_stackframeinfo();
717 /* Iterate over the whole stack until we reached the requested
722 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
723 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
724 stacktrace_stackframeinfo_next(&tmpsfi)) {
729 /* Skip builtin methods. */
731 if (m->flags & ACC_METHOD_BUILTIN)
734 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
735 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
736 (vframeStreamCommon::security_get_caller_frame). */
738 /* This is java.lang.reflect.Method.invoke(), skip it. */
740 if (m == method_java_lang_reflect_Method_invoke)
743 /* This is an auxiliary frame, skip it. */
745 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
749 /* We reached the requested depth. */
762 /* stacktrace_first_nonnull_classloader ****************************************
764 Returns the first non-null (user-defined) classloader on the stack.
765 If none is found NULL is returned.
770 *******************************************************************************/
772 classloader_t *stacktrace_first_nonnull_classloader(void)
774 stackframeinfo_t *sfi;
775 stackframeinfo_t tmpsfi;
780 if (opt_DebugStackTrace)
781 log_println("[stacktrace_first_nonnull_classloader]");
784 /* Get the stackframeinfo of the current thread. */
786 sfi = threads_get_current_stackframeinfo();
788 /* Iterate over the whole stack. */
790 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
791 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
792 stacktrace_stackframeinfo_next(&tmpsfi)) {
795 cl = class_get_classloader(m->clazz);
805 /* stacktrace_getClassContext **************************************************
807 Creates a Class context array.
810 the array of java.lang.Class objects, or
811 NULL if an exception has been thrown
813 *******************************************************************************/
815 java_handle_objectarray_t *stacktrace_getClassContext(void)
817 stackframeinfo_t *sfi;
818 stackframeinfo_t tmpsfi;
820 java_handle_objectarray_t *oa;
821 java_object_t **data;
825 CYCLES_STATS_DECLARE_AND_START
828 if (opt_DebugStackTrace)
829 log_println("[stacktrace_getClassContext]");
832 sfi = threads_get_current_stackframeinfo();
834 /* Get the depth of the current stack. */
836 depth = stacktrace_depth(sfi);
838 /* The first stackframe corresponds to the method whose
839 implementation calls this native function. We remove that
843 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
844 stacktrace_stackframeinfo_next(&tmpsfi);
846 /* Allocate the Class array. */
848 oa = builtin_anewarray(depth, class_java_lang_Class);
851 CYCLES_STATS_END(stacktrace_getClassContext);
856 /* Fill the Class array from the stacktrace list. */
860 data = LLNI_array_data(oa);
862 /* Iterate over the whole stack. */
867 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
868 stacktrace_stackframeinfo_next(&tmpsfi)) {
869 /* Get methodinfo. */
873 /* Skip builtin methods. */
875 if (m->flags & ACC_METHOD_BUILTIN)
878 /* Store the class in the array. */
880 data[i] = (java_object_t *) m->clazz;
887 CYCLES_STATS_END(stacktrace_getClassContext)
893 /* stacktrace_getCurrentClass **************************************************
895 Find the current class by walking the stack trace.
897 Quote from the JNI documentation:
899 In the Java 2 Platform, FindClass locates the class loader
900 associated with the current native method. If the native code
901 belongs to a system class, no class loader will be
902 involved. Otherwise, the proper class loader will be invoked to
903 load and link the named class. When FindClass is called through the
904 Invocation Interface, there is no current native method or its
905 associated class loader. In that case, the result of
906 ClassLoader.getBaseClassLoader is used."
908 *******************************************************************************/
910 #if defined(ENABLE_JAVASE)
911 classinfo *stacktrace_get_current_class(void)
913 stackframeinfo_t *sfi;
914 stackframeinfo_t tmpsfi;
917 CYCLES_STATS_DECLARE_AND_START;
920 if (opt_DebugStackTrace)
921 log_println("[stacktrace_get_current_class]");
924 /* Get the stackframeinfo of the current thread. */
926 sfi = threads_get_current_stackframeinfo();
928 /* If the stackframeinfo is NULL then FindClass is called through
929 the Invocation Interface and we return NULL */
932 CYCLES_STATS_END(stacktrace_getCurrentClass);
937 /* Iterate over the whole stack. */
939 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
940 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
941 stacktrace_stackframeinfo_next(&tmpsfi)) {
942 /* Get the methodinfo. */
946 if (m->clazz == class_java_security_PrivilegedAction) {
947 CYCLES_STATS_END(stacktrace_getCurrentClass);
952 if (m->clazz != NULL) {
953 CYCLES_STATS_END(stacktrace_getCurrentClass);
959 /* No Java method found on the stack. */
961 CYCLES_STATS_END(stacktrace_getCurrentClass);
965 #endif /* ENABLE_JAVASE */
968 /* stacktrace_get_stack ********************************************************
970 Create a 2-dimensional array for java.security.VMAccessControler.
974 NULL if an exception has been thrown
976 *******************************************************************************/
978 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
979 java_handle_objectarray_t *stacktrace_get_stack(void)
981 stackframeinfo_t *sfi;
982 stackframeinfo_t tmpsfi;
984 java_handle_objectarray_t *oa;
985 java_handle_objectarray_t *classes;
986 java_handle_objectarray_t *methodnames;
988 java_handle_t *string;
991 CYCLES_STATS_DECLARE_AND_START
994 if (opt_DebugStackTrace)
995 log_println("[stacktrace_get_stack]");
998 /* Get the stackframeinfo of the current thread. */
1000 sfi = threads_get_current_stackframeinfo();
1002 /* Get the depth of the current stack. */
1004 depth = stacktrace_depth(sfi);
1009 /* Allocate the required arrays. */
1011 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1016 classes = builtin_anewarray(depth, class_java_lang_Class);
1018 if (classes == NULL)
1021 methodnames = builtin_anewarray(depth, class_java_lang_String);
1023 if (methodnames == NULL)
1026 /* Set up the 2-dimensional array. */
1028 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1029 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1031 /* Iterate over the whole stack. */
1032 /* TODO We should use a critical section here to speed things
1037 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1038 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1039 stacktrace_stackframeinfo_next(&tmpsfi)) {
1040 /* Get the methodinfo. */
1044 /* Skip builtin methods. */
1046 if (m->flags & ACC_METHOD_BUILTIN)
1049 /* Store the class in the array. */
1050 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1053 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1055 /* Store the name in the array. */
1057 string = javastring_new(m->name);
1062 array_objectarray_element_set(methodnames, i, string);
1067 CYCLES_STATS_END(stacktrace_get_stack)
1072 CYCLES_STATS_END(stacktrace_get_stack)
1079 /* stacktrace_print_entry ****************************************************
1081 Print line for a stacktrace entry.
1084 m ............ methodinfo of the entry
1085 linenumber ... linenumber of the entry
1087 *******************************************************************************/
1089 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1097 if (m->flags & ACC_METHOD_BUILTIN)
1100 utf_display_printable_ascii_classname(m->clazz->name);
1103 utf_display_printable_ascii(m->name);
1104 utf_display_printable_ascii(m->descriptor);
1106 if (m->flags & ACC_NATIVE) {
1107 puts("(Native Method)");
1110 if (m->flags & ACC_METHOD_BUILTIN) {
1115 utf_display_printable_ascii(m->clazz->sourcefile);
1116 printf(":%d)\n", linenumber);
1124 /* stacktrace_print ************************************************************
1126 Print the given stacktrace with CACAO intern methods only (no Java
1129 This method is used by stacktrace_dump_trace and
1130 builtin_trace_exception.
1133 st ... stacktrace to print
1135 *******************************************************************************/
1137 void stacktrace_print(stacktrace_t *st)
1139 stacktrace_entry_t *ste;
1144 ste = &(st->entries[0]);
1146 for (i = 0; i < st->length; i++, ste++) {
1149 /* Get the line number. */
1151 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1153 stacktrace_print_entry(m, linenumber);
1158 /* stacktrace_print_current ****************************************************
1160 Print the current stacktrace of the current thread.
1162 NOTE: This function prints all frames of the stacktrace and does
1163 not skip frames like stacktrace_get.
1165 *******************************************************************************/
1167 void stacktrace_print_current(void)
1169 stackframeinfo_t *sfi;
1170 stackframeinfo_t tmpsfi;
1175 sfi = threads_get_current_stackframeinfo();
1178 puts("\t<<No stacktrace available>>");
1183 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1184 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1185 stacktrace_stackframeinfo_next(&tmpsfi)) {
1186 /* Get the methodinfo. */
1191 /* Get the line number. */
1193 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1195 stacktrace_print_entry(m, linenumber);
1200 /* stacktrace_print_of_thread **************************************************
1202 Print the current stacktrace of the given thread.
1207 *******************************************************************************/
1209 #if defined(ENABLE_THREADS)
1210 void stacktrace_print_of_thread(threadobject *t)
1212 stackframeinfo_t *sfi;
1213 stackframeinfo_t tmpsfi;
1218 /* Build a stacktrace for the passed thread. */
1220 sfi = t->_stackframeinfo;
1223 puts("\t<<No stacktrace available>>");
1228 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1229 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1230 stacktrace_stackframeinfo_next(&tmpsfi)) {
1231 /* Get the methodinfo. */
1236 /* Get the line number. */
1238 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1240 stacktrace_print_entry(m, linenumber);
1246 /* stacktrace_print_exception **************************************************
1248 Print the stacktrace of a given exception (more or less a wrapper
1249 to stacktrace_print).
1252 h ... handle of exception to print
1254 *******************************************************************************/
1256 void stacktrace_print_exception(java_handle_t *h)
1258 java_lang_Throwable *o;
1260 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1261 java_lang_VMThrowable *vmt;
1264 java_lang_Object *backtrace;
1265 java_handle_bytearray_t *ba;
1268 o = (java_lang_Throwable *) h;
1273 /* now print the stacktrace */
1275 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1277 LLNI_field_get_ref(o, vmState, vmt);
1278 LLNI_field_get_ref(vmt, vmdata, backtrace);
1280 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1282 LLNI_field_get_ref(o, backtrace, backtrace);
1285 # error unknown classpath configuration
1288 ba = (java_handle_bytearray_t *) backtrace;
1294 /* We need a critical section here as we use the byte-array data
1295 pointer directly. */
1297 LLNI_CRITICAL_START;
1299 st = (stacktrace_t *) LLNI_array_data(ba);
1301 stacktrace_print(st);
1307 #if defined(ENABLE_CYCLES_STATS)
1308 void stacktrace_print_cycles_stats(FILE *file)
1310 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1311 CYCLES_STATS_PRINT(stacktrace_get, file);
1312 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1313 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1314 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1322 * These are local overrides for various environment variables in Emacs.
1323 * Please do not remove this and leave it at the end of the file, where
1324 * Emacs will automagically detect them.
1325 * ---------------------------------------------------------------------
1328 * indent-tabs-mode: t
1332 * vim:noexpandtab:sw=4:ts=4: