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.hpp"
56 #include "toolbox/logging.h"
59 #include "vm/builtin.h"
60 #include "vm/cycles-stats.h"
61 #include "vm/exceptions.hpp"
62 #include "vm/string.hpp"
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/globals.hpp"
73 #include "vmcore/loader.h"
74 #include "vmcore/method.h"
75 #include "vmcore/options.h"
78 // FIXME Use C-linkage for now.
81 /* global variables ***********************************************************/
83 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
84 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
85 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
86 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
87 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
88 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
91 /* stacktrace_stackframeinfo_add ***********************************************
93 Fills a stackframe info structure with the given or calculated
94 values and adds it to the chain.
96 *******************************************************************************/
98 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
100 stackframeinfo_t *currentsfi;
102 #if defined(ENABLE_JIT)
106 /* Get current stackframe info. */
108 currentsfi = threads_get_current_stackframeinfo();
110 /* sometimes we don't have pv handy (e.g. in asmpart.S:
111 L_asm_call_jit_compiler_exception or in the interpreter). */
114 #if defined(ENABLE_INTRP)
116 pv = methodtree_find(ra);
120 #if defined(ENABLE_JIT)
121 # if defined(__SPARC_64__)
122 pv = md_get_pv_from_stackframe(sp);
124 pv = md_codegen_get_pv_from_pc(ra);
130 /* Get codeinfo pointer for the parent Java method. */
132 code = code_get_codeinfo_for_pv(pv);
135 /* assert(m != NULL); */
137 #if defined(ENABLE_JIT)
138 # if defined(ENABLE_INTRP)
139 /* When using the interpreter, we pass RA to the function. */
143 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
144 /* On i386 and x86_64 we always have to get the return address
146 /* m68k has return address on stack always */
147 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
148 the RA from stack. */
150 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
152 ra = md_stacktrace_get_returnaddress(sp, framesize);
154 /* If the method is a non-leaf function, we need to get the
155 return address from the stack. For leaf functions the
156 return address is set correctly. This makes the assembler
157 and the signal handler code simpler. The code is NULL is
158 the asm_vm_call_method special case. */
160 if ((code == NULL) || !code_is_leafmethod(code)) {
161 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
163 ra = md_stacktrace_get_returnaddress(sp, framesize);
166 # if defined(ENABLE_INTRP)
171 /* Calculate XPC when not given. The XPC is then the return
172 address of the current method minus 1 because the RA points to
173 the instruction after the call instruction. This is required
174 e.g. for method stubs. */
177 xpc = (void *) (((intptr_t) ra) - 1);
180 /* Fill new stackframeinfo structure. */
182 sfi->prev = currentsfi;
190 if (opt_DebugStackFrameInfo) {
192 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
193 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
194 method_print(sfi->code->m);
200 /* Store new stackframeinfo pointer. */
202 threads_set_current_stackframeinfo(sfi);
204 /* set the native world flag for the current thread */
205 /* ATTENTION: This flag tells the GC how to treat this thread in case of
206 a collection. Set this flag _after_ a valid stackframe info was set. */
208 THREAD_NATIVEWORLD_ENTER;
212 /* stacktrace_stackframeinfo_remove ********************************************
214 Remove the given stackframeinfo from the chain in the current
217 *******************************************************************************/
219 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
221 /* Clear the native world flag for the current thread. */
222 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
224 THREAD_NATIVEWORLD_EXIT;
227 if (opt_DebugStackFrameInfo) {
229 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
230 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
231 method_print(sfi->code->m);
237 /* Set previous stackframe info. */
239 threads_set_current_stackframeinfo(sfi->prev);
243 /* stacktrace_stackframeinfo_fill **********************************************
245 Fill the temporary stackframeinfo structure with the values given
249 tmpsfi ... temporary stackframeinfo
250 sfi ...... stackframeinfo to be used in the next iteration
252 *******************************************************************************/
254 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
258 assert(tmpsfi != NULL);
261 /* Fill the temporary stackframeinfo. */
263 tmpsfi->code = sfi->code;
264 tmpsfi->pv = sfi->pv;
265 tmpsfi->sp = sfi->sp;
266 tmpsfi->ra = sfi->ra;
267 tmpsfi->xpc = sfi->xpc;
269 /* Set the previous stackframe info of the temporary one to the
270 next in the chain. */
272 tmpsfi->prev = sfi->prev;
275 if (opt_DebugStackTrace)
276 log_println("[stacktrace fill]");
281 /* stacktrace_stackframeinfo_next **********************************************
283 Walk the stack (or the stackframeinfo-chain) to the next method and
284 return the new stackframe values in the temporary stackframeinfo
287 ATTENTION: This function does NOT skip builtin methods!
290 tmpsfi ... temporary stackframeinfo of current method
292 *******************************************************************************/
294 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
302 stackframeinfo_t *prevsfi;
306 assert(tmpsfi != NULL);
308 /* Get values from the stackframeinfo. */
316 /* Get the current stack frame size. */
318 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
320 /* Get the RA of the current stack frame (RA to the parent Java
321 method) if the current method is a non-leaf method. Otherwise
322 the value in the stackframeinfo is correct (from the signal
325 #if defined(ENABLE_JIT)
326 # if defined(ENABLE_INTRP)
328 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
332 if (!code_is_leafmethod(code))
333 ra = md_stacktrace_get_returnaddress(sp, framesize);
336 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
339 /* Get the PV for the parent Java method. */
341 #if defined(ENABLE_INTRP)
343 pv = methodtree_find(ra);
347 #if defined(ENABLE_JIT)
348 # if defined(__SPARC_64__)
349 sp = md_get_framepointer(sp);
350 pv = md_get_pv_from_stackframe(sp);
352 pv = md_codegen_get_pv_from_pc(ra);
357 /* Get the codeinfo pointer for the parent Java method. */
359 code = code_get_codeinfo_for_pv(pv);
361 /* Calculate the SP for the parent Java method. */
363 #if defined(ENABLE_INTRP)
365 sp = *(u1 **) (sp - framesize);
369 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
370 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
371 #elif defined(__SPARC_64__)
372 /* already has the new sp */
374 sp = (void *) (((intptr_t) sp) + framesize);
378 /* If the new codeinfo pointer is NULL we reached a
379 asm_vm_call_method function. In this case we get the next
380 values from the previous stackframeinfo in the chain.
381 Otherwise the new values have been calculated before. */
384 prevsfi = tmpsfi->prev;
386 /* If the previous stackframeinfo in the chain is NULL we
387 reached the top of the stacktrace. We set code and prev to
388 NULL to mark the end, which is checked in
389 stacktrace_stackframeinfo_end_check. */
391 if (prevsfi == NULL) {
397 /* Fill the temporary stackframeinfo with the new values. */
399 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
402 /* Store the new values in the stackframeinfo. NOTE: We
403 subtract 1 from the RA to get the XPC, because the RA
404 points to the instruction after the call instruction. */
410 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
414 /* Print current method information. */
416 if (opt_DebugStackTrace) {
418 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
419 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
421 method_print(tmpsfi->code->m);
429 /* stacktrace_stackframeinfo_end_check *****************************************
431 Check if we reached the end of the stacktrace.
434 tmpsfi ... temporary stackframeinfo of current method
437 true .... the end is reached
438 false ... the end is not reached
440 *******************************************************************************/
442 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
446 assert(tmpsfi != NULL);
448 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
450 if (opt_DebugStackTrace)
451 log_println("[stacktrace stop]");
461 /* stacktrace_depth ************************************************************
463 Calculates and returns the depth of the current stacktrace.
466 sfi ... stackframeinfo where to start the stacktrace
469 depth of the stacktrace
471 *******************************************************************************/
473 static int stacktrace_depth(stackframeinfo_t *sfi)
475 stackframeinfo_t tmpsfi;
480 if (opt_DebugStackTrace)
481 log_println("[stacktrace_depth]");
484 /* XXX This is not correct, but a workaround for threads-dump for
486 /* assert(sfi != NULL); */
490 /* Iterate over all stackframes. */
494 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
495 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
496 stacktrace_stackframeinfo_next(&tmpsfi)) {
497 /* Get methodinfo. */
501 /* Skip builtin methods. */
503 if (m->flags & ACC_METHOD_BUILTIN)
513 /* stacktrace_get **************************************************************
515 Builds and returns a stacktrace starting from the given stackframe
516 info and returns the stacktrace structure wrapped in a Java
517 byte-array to not confuse the GC.
520 sfi ... stackframe info to start stacktrace from
523 stacktrace as Java byte-array
525 *******************************************************************************/
527 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
529 stackframeinfo_t tmpsfi;
531 java_handle_bytearray_t *ba;
534 stacktrace_entry_t *ste;
536 bool skip_fillInStackTrace;
539 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
542 if (opt_DebugStackTrace)
543 log_println("[stacktrace_get]");
546 skip_fillInStackTrace = true;
549 depth = stacktrace_depth(sfi);
554 /* Allocate memory from the GC heap and copy the stacktrace
556 /* ATTENTION: Use a Java byte-array for this to not confuse the
558 /* FIXME: We waste some memory here as we skip some entries
561 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
563 ba = builtin_newarray_byte(ba_size);
568 /* Get a stacktrace entry pointer. */
569 /* ATTENTION: We need a critical section here because we use the
570 byte-array data pointer directly. */
574 st = (stacktrace_t *) LLNI_array_data(ba);
578 /* Iterate over the whole stack. */
580 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
581 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
582 stacktrace_stackframeinfo_next(&tmpsfi)) {
583 /* Get the methodinfo. */
587 /* Skip builtin methods. */
589 if (m->flags & ACC_METHOD_BUILTIN)
592 /* This logic is taken from
593 hotspot/src/share/vm/classfile/javaClasses.cpp
594 (java_lang_Throwable::fill_in_stack_trace). */
596 if (skip_fillInStackTrace == true) {
597 /* Check "fillInStackTrace" only once, so we negate the
598 flag after the first time check. */
600 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
601 /* For GNU Classpath we also need to skip
602 VMThrowable.fillInStackTrace(). */
604 if ((m->clazz == class_java_lang_VMThrowable) &&
605 (m->name == utf_fillInStackTrace))
609 skip_fillInStackTrace = false;
611 if (m->name == utf_fillInStackTrace)
615 /* Skip <init> methods of the exceptions klass. If there is
616 <init> methods that belongs to a superclass of the
617 exception we are going to skipping them in stack trace. */
619 if (skip_init == true) {
620 if ((m->name == utf_init) &&
621 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
625 /* If no "Throwable.init()" method found, we stop
626 checking it next time. */
632 /* Store the stacktrace entry and increment the pointer. */
634 ste->code = tmpsfi.code;
635 ste->pc = tmpsfi.xpc;
640 /* Store the number of entries in the stacktrace structure. */
642 st->length = ste - st->entries;
646 /* release dump memory */
648 /* dump_release(dumpsize); */
650 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
655 /* dump_release(dumpsize); */
657 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
664 /* stacktrace_get_current ******************************************************
666 Builds and returns a stacktrace from the current thread and returns
667 the stacktrace structure wrapped in a Java byte-array to not
671 stacktrace as Java byte-array
673 *******************************************************************************/
675 java_handle_bytearray_t *stacktrace_get_current(void)
677 stackframeinfo_t *sfi;
678 java_handle_bytearray_t *ba;
680 sfi = threads_get_current_stackframeinfo();
681 ba = stacktrace_get(sfi);
687 /* stacktrace_get_caller_class *************************************************
689 Get the class on the stack at the given depth. This function skips
690 various special classes or methods.
693 depth ... depth to get caller class of
698 *******************************************************************************/
700 #if defined(ENABLE_JAVASE)
701 classinfo *stacktrace_get_caller_class(int depth)
703 stackframeinfo_t *sfi;
704 stackframeinfo_t tmpsfi;
710 if (opt_DebugStackTrace)
711 log_println("[stacktrace_get_caller_class]");
714 /* Get the stackframeinfo of the current thread. */
716 sfi = threads_get_current_stackframeinfo();
718 /* Iterate over the whole stack until we reached the requested
723 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
724 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
725 stacktrace_stackframeinfo_next(&tmpsfi)) {
730 /* Skip builtin methods. */
732 if (m->flags & ACC_METHOD_BUILTIN)
735 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
736 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
737 (vframeStreamCommon::security_get_caller_frame). */
739 /* This is java.lang.reflect.Method.invoke(), skip it. */
741 if (m == method_java_lang_reflect_Method_invoke)
744 /* This is an auxiliary frame, skip it. */
746 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
750 /* We reached the requested depth. */
763 /* stacktrace_first_nonnull_classloader ****************************************
765 Returns the first non-null (user-defined) classloader on the stack.
766 If none is found NULL is returned.
771 *******************************************************************************/
773 classloader_t *stacktrace_first_nonnull_classloader(void)
775 stackframeinfo_t *sfi;
776 stackframeinfo_t tmpsfi;
781 if (opt_DebugStackTrace)
782 log_println("[stacktrace_first_nonnull_classloader]");
785 /* Get the stackframeinfo of the current thread. */
787 sfi = threads_get_current_stackframeinfo();
789 /* Iterate over the whole stack. */
791 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
792 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
793 stacktrace_stackframeinfo_next(&tmpsfi)) {
796 cl = class_get_classloader(m->clazz);
806 /* stacktrace_getClassContext **************************************************
808 Creates a Class context array.
811 the array of java.lang.Class objects, or
812 NULL if an exception has been thrown
814 *******************************************************************************/
816 java_handle_objectarray_t *stacktrace_getClassContext(void)
818 stackframeinfo_t *sfi;
819 stackframeinfo_t tmpsfi;
821 java_handle_objectarray_t *oa;
822 java_object_t **data;
826 CYCLES_STATS_DECLARE_AND_START
829 if (opt_DebugStackTrace)
830 log_println("[stacktrace_getClassContext]");
833 sfi = threads_get_current_stackframeinfo();
835 /* Get the depth of the current stack. */
837 depth = stacktrace_depth(sfi);
839 /* The first stackframe corresponds to the method whose
840 implementation calls this native function. We remove that
844 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
845 stacktrace_stackframeinfo_next(&tmpsfi);
847 /* Allocate the Class array. */
849 oa = builtin_anewarray(depth, class_java_lang_Class);
852 CYCLES_STATS_END(stacktrace_getClassContext);
857 /* Fill the Class array from the stacktrace list. */
861 data = LLNI_array_data(oa);
863 /* Iterate over the whole stack. */
868 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
869 stacktrace_stackframeinfo_next(&tmpsfi)) {
870 /* Get methodinfo. */
874 /* Skip builtin methods. */
876 if (m->flags & ACC_METHOD_BUILTIN)
879 /* Store the class in the array. */
881 data[i] = (java_object_t *) m->clazz;
888 CYCLES_STATS_END(stacktrace_getClassContext)
894 /* stacktrace_getCurrentClass **************************************************
896 Find the current class by walking the stack trace.
898 Quote from the JNI documentation:
900 In the Java 2 Platform, FindClass locates the class loader
901 associated with the current native method. If the native code
902 belongs to a system class, no class loader will be
903 involved. Otherwise, the proper class loader will be invoked to
904 load and link the named class. When FindClass is called through the
905 Invocation Interface, there is no current native method or its
906 associated class loader. In that case, the result of
907 ClassLoader.getBaseClassLoader is used."
909 *******************************************************************************/
911 #if defined(ENABLE_JAVASE)
912 classinfo *stacktrace_get_current_class(void)
914 stackframeinfo_t *sfi;
915 stackframeinfo_t tmpsfi;
918 CYCLES_STATS_DECLARE_AND_START;
921 if (opt_DebugStackTrace)
922 log_println("[stacktrace_get_current_class]");
925 /* Get the stackframeinfo of the current thread. */
927 sfi = threads_get_current_stackframeinfo();
929 /* If the stackframeinfo is NULL then FindClass is called through
930 the Invocation Interface and we return NULL */
933 CYCLES_STATS_END(stacktrace_getCurrentClass);
938 /* Iterate over the whole stack. */
940 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
941 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
942 stacktrace_stackframeinfo_next(&tmpsfi)) {
943 /* Get the methodinfo. */
947 if (m->clazz == class_java_security_PrivilegedAction) {
948 CYCLES_STATS_END(stacktrace_getCurrentClass);
953 if (m->clazz != NULL) {
954 CYCLES_STATS_END(stacktrace_getCurrentClass);
960 /* No Java method found on the stack. */
962 CYCLES_STATS_END(stacktrace_getCurrentClass);
966 #endif /* ENABLE_JAVASE */
969 /* stacktrace_get_stack ********************************************************
971 Create a 2-dimensional array for java.security.VMAccessControler.
975 NULL if an exception has been thrown
977 *******************************************************************************/
979 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
980 java_handle_objectarray_t *stacktrace_get_stack(void)
982 stackframeinfo_t *sfi;
983 stackframeinfo_t tmpsfi;
985 java_handle_objectarray_t *oa;
986 java_handle_objectarray_t *classes;
987 java_handle_objectarray_t *methodnames;
989 java_handle_t *string;
992 CYCLES_STATS_DECLARE_AND_START
995 if (opt_DebugStackTrace)
996 log_println("[stacktrace_get_stack]");
999 /* Get the stackframeinfo of the current thread. */
1001 sfi = threads_get_current_stackframeinfo();
1003 /* Get the depth of the current stack. */
1005 depth = stacktrace_depth(sfi);
1010 /* Allocate the required arrays. */
1012 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1017 classes = builtin_anewarray(depth, class_java_lang_Class);
1019 if (classes == NULL)
1022 methodnames = builtin_anewarray(depth, class_java_lang_String);
1024 if (methodnames == NULL)
1027 /* Set up the 2-dimensional array. */
1029 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1030 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1032 /* Iterate over the whole stack. */
1033 /* TODO We should use a critical section here to speed things
1038 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1039 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1040 stacktrace_stackframeinfo_next(&tmpsfi)) {
1041 /* Get the methodinfo. */
1045 /* Skip builtin methods. */
1047 if (m->flags & ACC_METHOD_BUILTIN)
1050 /* Store the class in the array. */
1051 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1054 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1056 /* Store the name in the array. */
1058 string = javastring_new(m->name);
1063 array_objectarray_element_set(methodnames, i, string);
1068 CYCLES_STATS_END(stacktrace_get_stack)
1073 CYCLES_STATS_END(stacktrace_get_stack)
1080 /* stacktrace_print_entry ****************************************************
1082 Print line for a stacktrace entry.
1085 m ............ methodinfo of the entry
1086 linenumber ... linenumber of the entry
1088 *******************************************************************************/
1090 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1098 if (m->flags & ACC_METHOD_BUILTIN)
1101 utf_display_printable_ascii_classname(m->clazz->name);
1104 utf_display_printable_ascii(m->name);
1105 utf_display_printable_ascii(m->descriptor);
1107 if (m->flags & ACC_NATIVE) {
1108 puts("(Native Method)");
1111 if (m->flags & ACC_METHOD_BUILTIN) {
1116 utf_display_printable_ascii(m->clazz->sourcefile);
1117 printf(":%d)\n", linenumber);
1125 /* stacktrace_print ************************************************************
1127 Print the given stacktrace with CACAO intern methods only (no Java
1130 This method is used by stacktrace_dump_trace and
1131 builtin_trace_exception.
1134 st ... stacktrace to print
1136 *******************************************************************************/
1138 void stacktrace_print(stacktrace_t *st)
1140 stacktrace_entry_t *ste;
1145 ste = &(st->entries[0]);
1147 for (i = 0; i < st->length; i++, ste++) {
1150 /* Get the line number. */
1152 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1154 stacktrace_print_entry(m, linenumber);
1159 /* stacktrace_print_current ****************************************************
1161 Print the current stacktrace of the current thread.
1163 NOTE: This function prints all frames of the stacktrace and does
1164 not skip frames like stacktrace_get.
1166 *******************************************************************************/
1168 void stacktrace_print_current(void)
1170 stackframeinfo_t *sfi;
1171 stackframeinfo_t tmpsfi;
1176 sfi = threads_get_current_stackframeinfo();
1179 puts("\t<<No stacktrace available>>");
1184 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1185 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1186 stacktrace_stackframeinfo_next(&tmpsfi)) {
1187 /* Get the methodinfo. */
1192 /* Get the line number. */
1194 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1196 stacktrace_print_entry(m, linenumber);
1201 /* stacktrace_print_of_thread **************************************************
1203 Print the current stacktrace of the given thread.
1208 *******************************************************************************/
1210 #if defined(ENABLE_THREADS)
1211 void stacktrace_print_of_thread(threadobject *t)
1213 stackframeinfo_t *sfi;
1214 stackframeinfo_t tmpsfi;
1219 /* Build a stacktrace for the passed thread. */
1221 sfi = t->_stackframeinfo;
1224 puts("\t<<No stacktrace available>>");
1229 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1230 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1231 stacktrace_stackframeinfo_next(&tmpsfi)) {
1232 /* Get the methodinfo. */
1237 /* Get the line number. */
1239 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1241 stacktrace_print_entry(m, linenumber);
1247 /* stacktrace_print_exception **************************************************
1249 Print the stacktrace of a given exception (more or less a wrapper
1250 to stacktrace_print).
1253 h ... handle of exception to print
1255 *******************************************************************************/
1257 void stacktrace_print_exception(java_handle_t *h)
1259 java_lang_Throwable *o;
1261 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1262 java_lang_VMThrowable *vmt;
1265 java_lang_Object *backtrace;
1266 java_handle_bytearray_t *ba;
1269 o = (java_lang_Throwable *) h;
1274 /* now print the stacktrace */
1276 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1278 LLNI_field_get_ref(o, vmState, vmt);
1279 LLNI_field_get_ref(vmt, vmdata, backtrace);
1281 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1283 LLNI_field_get_ref(o, backtrace, backtrace);
1286 # error unknown classpath configuration
1289 ba = (java_handle_bytearray_t *) backtrace;
1295 /* We need a critical section here as we use the byte-array data
1296 pointer directly. */
1298 LLNI_CRITICAL_START;
1300 st = (stacktrace_t *) LLNI_array_data(ba);
1302 stacktrace_print(st);
1308 #if defined(ENABLE_CYCLES_STATS)
1309 void stacktrace_print_cycles_stats(FILE *file)
1311 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1312 CYCLES_STATS_PRINT(stacktrace_get, file);
1313 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1314 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1315 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1323 * These are local overrides for various environment variables in Emacs.
1324 * Please do not remove this and leave it at the end of the file, where
1325 * Emacs will automagically detect them.
1326 * ---------------------------------------------------------------------
1329 * indent-tabs-mode: t
1333 * vim:noexpandtab:sw=4:ts=4: