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_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 /* global variables ***********************************************************/
79 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
80 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
81 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
82 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
83 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
84 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
87 /* stacktrace_stackframeinfo_add ***********************************************
89 Fills a stackframe info structure with the given or calculated
90 values and adds it to the chain.
92 *******************************************************************************/
94 void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
96 stackframeinfo_t *currentsfi;
98 #if defined(ENABLE_JIT)
102 /* Get current stackframe info. */
104 currentsfi = threads_get_current_stackframeinfo();
106 /* sometimes we don't have pv handy (e.g. in asmpart.S:
107 L_asm_call_jit_compiler_exception or in the interpreter). */
110 #if defined(ENABLE_INTRP)
112 pv = methodtree_find(ra);
116 #if defined(ENABLE_JIT)
117 # if defined(__SPARC_64__)
118 pv = md_get_pv_from_stackframe(sp);
120 pv = md_codegen_get_pv_from_pc(ra);
126 /* Get codeinfo pointer for the parent Java method. */
128 code = code_get_codeinfo_for_pv(pv);
131 /* assert(m != NULL); */
133 #if defined(ENABLE_JIT)
134 # if defined(ENABLE_INTRP)
135 /* When using the interpreter, we pass RA to the function. */
139 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
140 /* On i386 and x86_64 we always have to get the return address
142 /* m68k has return address on stack always */
143 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
144 the RA from stack. */
146 framesize = *((u4 *) (pv + FrameSize));
148 ra = md_stacktrace_get_returnaddress(sp, framesize);
150 /* If the method is a non-leaf function, we need to get the
151 return address from the stack. For leaf functions the
152 return address is set correctly. This makes the assembler
153 and the signal handler code simpler. The code is NULL is
154 the asm_vm_call_method special case. */
156 if ((code == NULL) || !code_is_leafmethod(code)) {
157 framesize = *((u4 *) (pv + FrameSize));
159 ra = md_stacktrace_get_returnaddress(sp, framesize);
162 # if defined(ENABLE_INTRP)
167 /* Calculate XPC when not given. The XPC is then the return
168 address of the current method minus 1 because the RA points to
169 the instruction after the call instruction. This is required
170 e.g. for method stubs. */
173 xpc = (void *) (((intptr_t) ra) - 1);
176 /* Fill new stackframeinfo structure. */
178 sfi->prev = currentsfi;
186 if (opt_DebugStackFrameInfo) {
188 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
189 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
190 method_print(sfi->code->m);
196 /* Store new stackframeinfo pointer. */
198 threads_set_current_stackframeinfo(sfi);
200 /* set the native world flag for the current thread */
201 /* ATTENTION: This flag tells the GC how to treat this thread in case of
202 a collection. Set this flag _after_ a valid stackframe info was set. */
204 THREAD_NATIVEWORLD_ENTER;
208 /* stacktrace_stackframeinfo_remove ********************************************
210 Remove the given stackframeinfo from the chain in the current
213 *******************************************************************************/
215 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
217 /* Clear the native world flag for the current thread. */
218 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
220 THREAD_NATIVEWORLD_EXIT;
223 if (opt_DebugStackFrameInfo) {
225 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
226 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
227 method_print(sfi->code->m);
233 /* Set previous stackframe info. */
235 threads_set_current_stackframeinfo(sfi->prev);
239 /* stacktrace_stackframeinfo_fill **********************************************
241 Fill the temporary stackframeinfo structure with the values given
245 tmpsfi ... temporary stackframeinfo
246 sfi ...... stackframeinfo to be used in the next iteration
248 *******************************************************************************/
250 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
254 assert(tmpsfi != NULL);
257 /* Fill the temporary stackframeinfo. */
259 tmpsfi->code = sfi->code;
260 tmpsfi->pv = sfi->pv;
261 tmpsfi->sp = sfi->sp;
262 tmpsfi->ra = sfi->ra;
263 tmpsfi->xpc = sfi->xpc;
265 /* Set the previous stackframe info of the temporary one to the
266 next in the chain. */
268 tmpsfi->prev = sfi->prev;
271 if (opt_DebugStackTrace)
272 log_println("[stacktrace fill]");
277 /* stacktrace_stackframeinfo_next **********************************************
279 Walk the stack (or the stackframeinfo-chain) to the next method and
280 return the new stackframe values in the temporary stackframeinfo
283 ATTENTION: This function does NOT skip builtin methods!
286 tmpsfi ... temporary stackframeinfo of current method
288 *******************************************************************************/
290 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
298 stackframeinfo_t *prevsfi;
302 assert(tmpsfi != NULL);
304 /* Get values from the stackframeinfo. */
312 /* Get the current stack frame size. */
314 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
316 /* Get the RA of the current stack frame (RA to the parent Java
317 method) if the current method is a non-leaf method. Otherwise
318 the value in the stackframeinfo is correct (from the signal
321 #if defined(ENABLE_JIT)
322 # if defined(ENABLE_INTRP)
324 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
328 if (!code_is_leafmethod(code))
329 ra = md_stacktrace_get_returnaddress(sp, framesize);
332 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
335 /* Get the PV for the parent Java method. */
337 #if defined(ENABLE_INTRP)
339 pv = methodtree_find(ra);
343 #if defined(ENABLE_JIT)
344 # if defined(__SPARC_64__)
345 sp = md_get_framepointer(sp);
346 pv = md_get_pv_from_stackframe(sp);
348 pv = md_codegen_get_pv_from_pc(ra);
353 /* Get the codeinfo pointer for the parent Java method. */
355 code = code_get_codeinfo_for_pv(pv);
357 /* Calculate the SP for the parent Java method. */
359 #if defined(ENABLE_INTRP)
361 sp = *(u1 **) (sp - framesize);
365 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
366 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
367 #elif defined(__SPARC_64__)
368 /* already has the new sp */
370 sp = (void *) (((intptr_t) sp) + framesize);
374 /* If the new codeinfo pointer is NULL we reached a
375 asm_vm_call_method function. In this case we get the next
376 values from the previous stackframeinfo in the chain.
377 Otherwise the new values have been calculated before. */
380 prevsfi = tmpsfi->prev;
382 /* If the previous stackframeinfo in the chain is NULL we
383 reached the top of the stacktrace. We set code and prev to
384 NULL to mark the end, which is checked in
385 stacktrace_stackframeinfo_end_check. */
387 if (prevsfi == NULL) {
393 /* Fill the temporary stackframeinfo with the new values. */
395 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
398 /* Store the new values in the stackframeinfo. NOTE: We
399 subtract 1 from the RA to get the XPC, because the RA
400 points to the instruction after the call instruction. */
406 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
410 /* Print current method information. */
412 if (opt_DebugStackTrace) {
414 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
415 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
417 method_print(tmpsfi->code->m);
425 /* stacktrace_stackframeinfo_end_check *****************************************
427 Check if we reached the end of the stacktrace.
430 tmpsfi ... temporary stackframeinfo of current method
433 true .... the end is reached
434 false ... the end is not reached
436 *******************************************************************************/
438 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
442 assert(tmpsfi != NULL);
444 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
446 if (opt_DebugStackTrace)
447 log_println("[stacktrace stop]");
457 /* stacktrace_depth ************************************************************
459 Calculates and returns the depth of the current stacktrace.
462 sfi ... stackframeinfo where to start the stacktrace
465 depth of the stacktrace
467 *******************************************************************************/
469 static int stacktrace_depth(stackframeinfo_t *sfi)
471 stackframeinfo_t tmpsfi;
476 if (opt_DebugStackTrace)
477 log_println("[stacktrace_depth]");
480 /* XXX This is not correct, but a workaround for threads-dump for
482 /* assert(sfi != NULL); */
486 /* Iterate over all stackframes. */
490 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
491 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
492 stacktrace_stackframeinfo_next(&tmpsfi)) {
493 /* Get methodinfo. */
497 /* Skip builtin methods. */
499 if (m->flags & ACC_METHOD_BUILTIN)
509 /* stacktrace_get **************************************************************
511 Builds and returns a stacktrace starting from the given stackframe
512 info and returns the stacktrace structure wrapped in a Java
513 byte-array to not confuse the GC.
516 sfi ... stackframe info to start stacktrace from
519 stacktrace as Java byte-array
521 *******************************************************************************/
523 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
525 stackframeinfo_t tmpsfi;
527 java_handle_bytearray_t *ba;
530 stacktrace_entry_t *ste;
532 bool skip_fillInStackTrace;
535 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
538 if (opt_DebugStackTrace)
539 log_println("[stacktrace_get]");
542 skip_fillInStackTrace = true;
545 depth = stacktrace_depth(sfi);
550 /* Allocate memory from the GC heap and copy the stacktrace
552 /* ATTENTION: Use a Java byte-array for this to not confuse the
554 /* FIXME: We waste some memory here as we skip some entries
557 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
559 ba = builtin_newarray_byte(ba_size);
564 /* Get a stacktrace entry pointer. */
565 /* ATTENTION: We need a critical section here because we use the
566 byte-array data pointer directly. */
570 st = (stacktrace_t *) LLNI_array_data(ba);
574 /* Iterate over the whole stack. */
576 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
577 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
578 stacktrace_stackframeinfo_next(&tmpsfi)) {
579 /* Get the methodinfo. */
583 /* Skip builtin methods. */
585 if (m->flags & ACC_METHOD_BUILTIN)
588 /* This logic is taken from
589 hotspot/src/share/vm/classfile/javaClasses.cpp
590 (java_lang_Throwable::fill_in_stack_trace). */
592 if (skip_fillInStackTrace == true) {
593 /* Check "fillInStackTrace" only once, so we negate the
594 flag after the first time check. */
596 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
597 /* For GNU Classpath we also need to skip
598 VMThrowable.fillInStackTrace(). */
600 if ((m->clazz == class_java_lang_VMThrowable) &&
601 (m->name == utf_fillInStackTrace))
605 skip_fillInStackTrace = false;
607 if (m->name == utf_fillInStackTrace)
611 /* Skip <init> methods of the exceptions klass. If there is
612 <init> methods that belongs to a superclass of the
613 exception we are going to skipping them in stack trace. */
615 if (skip_init == true) {
616 if ((m->name == utf_init) &&
617 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
621 /* If no "Throwable.init()" method found, we stop
622 checking it next time. */
628 /* Store the stacktrace entry and increment the pointer. */
630 ste->code = tmpsfi.code;
631 ste->pc = tmpsfi.xpc;
636 /* Store the number of entries in the stacktrace structure. */
638 st->length = ste - st->entries;
642 /* release dump memory */
644 /* dump_release(dumpsize); */
646 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
651 /* dump_release(dumpsize); */
653 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
660 /* stacktrace_get_current ******************************************************
662 Builds and returns a stacktrace from the current thread and returns
663 the stacktrace structure wrapped in a Java byte-array to not
667 stacktrace as Java byte-array
669 *******************************************************************************/
671 java_handle_bytearray_t *stacktrace_get_current(void)
673 stackframeinfo_t *sfi;
674 java_handle_bytearray_t *ba;
676 sfi = threads_get_current_stackframeinfo();
677 ba = stacktrace_get(sfi);
683 /* stacktrace_get_caller_class *************************************************
685 Get the class on the stack at the given depth. This function skips
686 various special classes or methods.
689 depth ... depth to get caller class of
694 *******************************************************************************/
696 #if defined(ENABLE_JAVASE)
697 classinfo *stacktrace_get_caller_class(int depth)
699 stackframeinfo_t *sfi;
700 stackframeinfo_t tmpsfi;
706 if (opt_DebugStackTrace)
707 log_println("[stacktrace_get_caller_class]");
710 /* Get the stackframeinfo of the current thread. */
712 sfi = threads_get_current_stackframeinfo();
714 /* Iterate over the whole stack until we reached the requested
719 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
720 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
721 stacktrace_stackframeinfo_next(&tmpsfi)) {
726 /* Skip builtin methods. */
728 if (m->flags & ACC_METHOD_BUILTIN)
731 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
732 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
733 (vframeStreamCommon::security_get_caller_frame). */
735 /* This is java.lang.reflect.Method.invoke(), skip it. */
737 if (m == method_java_lang_reflect_Method_invoke)
740 /* This is an auxiliary frame, skip it. */
742 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
746 /* We reached the requested depth. */
759 /* stacktrace_first_nonnull_classloader ****************************************
761 Returns the first non-null (user-defined) classloader on the stack.
762 If none is found NULL is returned.
767 *******************************************************************************/
769 classloader_t *stacktrace_first_nonnull_classloader(void)
771 stackframeinfo_t *sfi;
772 stackframeinfo_t tmpsfi;
777 if (opt_DebugStackTrace)
778 log_println("[stacktrace_first_nonnull_classloader]");
781 /* Get the stackframeinfo of the current thread. */
783 sfi = threads_get_current_stackframeinfo();
785 /* Iterate over the whole stack. */
787 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
788 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
789 stacktrace_stackframeinfo_next(&tmpsfi)) {
792 cl = class_get_classloader(m->clazz);
802 /* stacktrace_getClassContext **************************************************
804 Creates a Class context array.
807 the array of java.lang.Class objects, or
808 NULL if an exception has been thrown
810 *******************************************************************************/
812 java_handle_objectarray_t *stacktrace_getClassContext(void)
814 stackframeinfo_t *sfi;
815 stackframeinfo_t tmpsfi;
817 java_handle_objectarray_t *oa;
818 java_object_t **data;
822 CYCLES_STATS_DECLARE_AND_START
825 if (opt_DebugStackTrace)
826 log_println("[stacktrace_getClassContext]");
829 sfi = threads_get_current_stackframeinfo();
831 /* Get the depth of the current stack. */
833 depth = stacktrace_depth(sfi);
835 /* The first stackframe corresponds to the method whose
836 implementation calls this native function. We remove that
840 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
841 stacktrace_stackframeinfo_next(&tmpsfi);
843 /* Allocate the Class array. */
845 oa = builtin_anewarray(depth, class_java_lang_Class);
848 CYCLES_STATS_END(stacktrace_getClassContext);
853 /* Fill the Class array from the stacktrace list. */
857 data = LLNI_array_data(oa);
859 /* Iterate over the whole stack. */
864 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
865 stacktrace_stackframeinfo_next(&tmpsfi)) {
866 /* Get methodinfo. */
870 /* Skip builtin methods. */
872 if (m->flags & ACC_METHOD_BUILTIN)
875 /* Store the class in the array. */
877 data[i] = (java_object_t *) m->clazz;
884 CYCLES_STATS_END(stacktrace_getClassContext)
890 /* stacktrace_getCurrentClass **************************************************
892 Find the current class by walking the stack trace.
894 Quote from the JNI documentation:
896 In the Java 2 Platform, FindClass locates the class loader
897 associated with the current native method. If the native code
898 belongs to a system class, no class loader will be
899 involved. Otherwise, the proper class loader will be invoked to
900 load and link the named class. When FindClass is called through the
901 Invocation Interface, there is no current native method or its
902 associated class loader. In that case, the result of
903 ClassLoader.getBaseClassLoader is used."
905 *******************************************************************************/
907 #if defined(ENABLE_JAVASE)
908 classinfo *stacktrace_get_current_class(void)
910 stackframeinfo_t *sfi;
911 stackframeinfo_t tmpsfi;
914 CYCLES_STATS_DECLARE_AND_START;
917 if (opt_DebugStackTrace)
918 log_println("[stacktrace_get_current_class]");
921 /* Get the stackframeinfo of the current thread. */
923 sfi = threads_get_current_stackframeinfo();
925 /* If the stackframeinfo is NULL then FindClass is called through
926 the Invocation Interface and we return NULL */
929 CYCLES_STATS_END(stacktrace_getCurrentClass);
934 /* Iterate over the whole stack. */
936 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
937 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
938 stacktrace_stackframeinfo_next(&tmpsfi)) {
939 /* Get the methodinfo. */
943 if (m->clazz == class_java_security_PrivilegedAction) {
944 CYCLES_STATS_END(stacktrace_getCurrentClass);
949 if (m->clazz != NULL) {
950 CYCLES_STATS_END(stacktrace_getCurrentClass);
956 /* No Java method found on the stack. */
958 CYCLES_STATS_END(stacktrace_getCurrentClass);
962 #endif /* ENABLE_JAVASE */
965 /* stacktrace_get_stack ********************************************************
967 Create a 2-dimensional array for java.security.VMAccessControler.
971 NULL if an exception has been thrown
973 *******************************************************************************/
975 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
976 java_handle_objectarray_t *stacktrace_get_stack(void)
978 stackframeinfo_t *sfi;
979 stackframeinfo_t tmpsfi;
981 java_handle_objectarray_t *oa;
982 java_handle_objectarray_t *classes;
983 java_handle_objectarray_t *methodnames;
985 java_handle_t *string;
988 CYCLES_STATS_DECLARE_AND_START
991 if (opt_DebugStackTrace)
992 log_println("[stacktrace_get_stack]");
995 /* Get the stackframeinfo of the current thread. */
997 sfi = threads_get_current_stackframeinfo();
999 /* Get the depth of the current stack. */
1001 depth = stacktrace_depth(sfi);
1006 /* Allocate the required arrays. */
1008 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1013 classes = builtin_anewarray(depth, class_java_lang_Class);
1015 if (classes == NULL)
1018 methodnames = builtin_anewarray(depth, class_java_lang_String);
1020 if (methodnames == NULL)
1023 /* Set up the 2-dimensional array. */
1025 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1026 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1028 /* Iterate over the whole stack. */
1029 /* TODO We should use a critical section here to speed things
1034 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1035 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1036 stacktrace_stackframeinfo_next(&tmpsfi)) {
1037 /* Get the methodinfo. */
1041 /* Skip builtin methods. */
1043 if (m->flags & ACC_METHOD_BUILTIN)
1046 /* Store the class in the array. */
1047 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1050 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1052 /* Store the name in the array. */
1054 string = javastring_new(m->name);
1059 array_objectarray_element_set(methodnames, i, string);
1064 CYCLES_STATS_END(stacktrace_get_stack)
1069 CYCLES_STATS_END(stacktrace_get_stack)
1076 /* stacktrace_print_entry ****************************************************
1078 Print line for a stacktrace entry.
1081 m ............ methodinfo of the entry
1082 linenumber ... linenumber of the entry
1084 *******************************************************************************/
1086 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1094 if (m->flags & ACC_METHOD_BUILTIN)
1097 utf_display_printable_ascii_classname(m->clazz->name);
1100 utf_display_printable_ascii(m->name);
1101 utf_display_printable_ascii(m->descriptor);
1103 if (m->flags & ACC_NATIVE) {
1104 puts("(Native Method)");
1107 if (m->flags & ACC_METHOD_BUILTIN) {
1112 utf_display_printable_ascii(m->clazz->sourcefile);
1113 printf(":%d)\n", linenumber);
1121 /* stacktrace_print ************************************************************
1123 Print the given stacktrace with CACAO intern methods only (no Java
1126 This method is used by stacktrace_dump_trace and
1127 builtin_trace_exception.
1130 st ... stacktrace to print
1132 *******************************************************************************/
1134 void stacktrace_print(stacktrace_t *st)
1136 stacktrace_entry_t *ste;
1141 ste = &(st->entries[0]);
1143 for (i = 0; i < st->length; i++, ste++) {
1146 /* Get the line number. */
1148 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1150 stacktrace_print_entry(m, linenumber);
1155 /* stacktrace_print_current ****************************************************
1157 Print the current stacktrace of the current thread.
1159 NOTE: This function prints all frames of the stacktrace and does
1160 not skip frames like stacktrace_get.
1162 *******************************************************************************/
1164 void stacktrace_print_current(void)
1166 stackframeinfo_t *sfi;
1167 stackframeinfo_t tmpsfi;
1172 sfi = threads_get_current_stackframeinfo();
1175 puts("\t<<No stacktrace available>>");
1180 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1181 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1182 stacktrace_stackframeinfo_next(&tmpsfi)) {
1183 /* Get the methodinfo. */
1188 /* Get the line number. */
1190 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1192 stacktrace_print_entry(m, linenumber);
1197 /* stacktrace_print_of_thread **************************************************
1199 Print the current stacktrace of the given thread.
1204 *******************************************************************************/
1206 #if defined(ENABLE_THREADS)
1207 void stacktrace_print_of_thread(threadobject *t)
1209 stackframeinfo_t *sfi;
1210 stackframeinfo_t tmpsfi;
1215 /* Build a stacktrace for the passed thread. */
1217 sfi = t->_stackframeinfo;
1220 puts("\t<<No stacktrace available>>");
1225 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1226 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1227 stacktrace_stackframeinfo_next(&tmpsfi)) {
1228 /* Get the methodinfo. */
1233 /* Get the line number. */
1235 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1237 stacktrace_print_entry(m, linenumber);
1243 /* stacktrace_print_exception **************************************************
1245 Print the stacktrace of a given exception (more or less a wrapper
1246 to stacktrace_print).
1249 h ... handle of exception to print
1251 *******************************************************************************/
1253 void stacktrace_print_exception(java_handle_t *h)
1255 java_lang_Throwable *o;
1257 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1258 java_lang_VMThrowable *vmt;
1261 java_lang_Object *backtrace;
1262 java_handle_bytearray_t *ba;
1265 o = (java_lang_Throwable *) h;
1270 /* now print the stacktrace */
1272 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1274 LLNI_field_get_ref(o, vmState, vmt);
1275 LLNI_field_get_ref(vmt, vmdata, backtrace);
1277 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1279 LLNI_field_get_ref(o, backtrace, backtrace);
1282 # error unknown classpath configuration
1285 ba = (java_handle_bytearray_t *) backtrace;
1291 /* We need a critical section here as we use the byte-array data
1292 pointer directly. */
1294 LLNI_CRITICAL_START;
1296 st = (stacktrace_t *) LLNI_array_data(ba);
1298 stacktrace_print(st);
1304 #if defined(ENABLE_CYCLES_STATS)
1305 void stacktrace_print_cycles_stats(FILE *file)
1307 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1308 CYCLES_STATS_PRINT(stacktrace_get, file);
1309 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1310 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1311 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1317 * These are local overrides for various environment variables in Emacs.
1318 * Please do not remove this and leave it at the end of the file, where
1319 * Emacs will automagically detect them.
1320 * ---------------------------------------------------------------------
1323 * indent-tabs-mode: t
1327 * vim:noexpandtab:sw=4:ts=4: