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 "threads/thread.hpp"
48 #include "toolbox/logging.h"
51 #include "vm/builtin.h"
52 #include "vm/cycles-stats.h"
53 #include "vm/exceptions.hpp"
54 #include "vm/string.hpp"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/codegen-common.h"
59 #include "vm/jit/linenumbertable.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/methodtree.h"
63 #include "vmcore/class.h"
64 #include "vmcore/globals.hpp"
65 #include "vmcore/javaobjects.hpp"
66 #include "vmcore/loader.h"
67 #include "vmcore/method.h"
68 #include "vmcore/options.h"
71 // FIXME Use C-linkage for now.
74 /* global variables ***********************************************************/
76 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
77 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
78 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
79 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
80 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
81 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
84 /* stacktrace_stackframeinfo_add ***********************************************
86 Fills a stackframe info structure with the given or calculated
87 values and adds it to the chain.
89 *******************************************************************************/
91 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
93 stackframeinfo_t *currentsfi;
95 #if defined(ENABLE_JIT)
99 /* Get current stackframe info. */
101 currentsfi = threads_get_current_stackframeinfo();
103 /* sometimes we don't have pv handy (e.g. in asmpart.S:
104 L_asm_call_jit_compiler_exception or in the interpreter). */
107 #if defined(ENABLE_INTRP)
109 pv = methodtree_find(ra);
113 #if defined(ENABLE_JIT)
114 # if defined(__SPARC_64__)
115 pv = md_get_pv_from_stackframe(sp);
117 pv = md_codegen_get_pv_from_pc(ra);
123 /* Get codeinfo pointer for the parent Java method. */
125 code = code_get_codeinfo_for_pv(pv);
128 /* assert(m != NULL); */
130 #if defined(ENABLE_JIT)
131 # if defined(ENABLE_INTRP)
132 /* When using the interpreter, we pass RA to the function. */
136 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
137 /* On i386 and x86_64 we always have to get the return address
139 /* m68k has return address on stack always */
140 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
141 the RA from stack. */
143 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
145 ra = md_stacktrace_get_returnaddress(sp, framesize);
147 /* If the method is a non-leaf function, we need to get the
148 return address from the stack. For leaf functions the
149 return address is set correctly. This makes the assembler
150 and the signal handler code simpler. The code is NULL is
151 the asm_vm_call_method special case. */
153 if ((code == NULL) || !code_is_leafmethod(code)) {
154 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
156 ra = md_stacktrace_get_returnaddress(sp, framesize);
159 # if defined(ENABLE_INTRP)
164 /* Calculate XPC when not given. The XPC is then the return
165 address of the current method minus 1 because the RA points to
166 the instruction after the call instruction. This is required
167 e.g. for method stubs. */
170 xpc = (void *) (((intptr_t) ra) - 1);
173 /* Fill new stackframeinfo structure. */
175 sfi->prev = currentsfi;
183 if (opt_DebugStackFrameInfo) {
185 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
186 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
187 method_print(sfi->code->m);
193 /* Store new stackframeinfo pointer. */
195 threads_set_current_stackframeinfo(sfi);
197 /* set the native world flag for the current thread */
198 /* ATTENTION: This flag tells the GC how to treat this thread in case of
199 a collection. Set this flag _after_ a valid stackframe info was set. */
201 THREAD_NATIVEWORLD_ENTER;
205 /* stacktrace_stackframeinfo_remove ********************************************
207 Remove the given stackframeinfo from the chain in the current
210 *******************************************************************************/
212 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
214 /* Clear the native world flag for the current thread. */
215 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
217 THREAD_NATIVEWORLD_EXIT;
220 if (opt_DebugStackFrameInfo) {
222 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
223 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
224 method_print(sfi->code->m);
230 /* Set previous stackframe info. */
232 threads_set_current_stackframeinfo(sfi->prev);
236 /* stacktrace_stackframeinfo_fill **********************************************
238 Fill the temporary stackframeinfo structure with the values given
242 tmpsfi ... temporary stackframeinfo
243 sfi ...... stackframeinfo to be used in the next iteration
245 *******************************************************************************/
247 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
251 assert(tmpsfi != NULL);
254 /* Fill the temporary stackframeinfo. */
256 tmpsfi->code = sfi->code;
257 tmpsfi->pv = sfi->pv;
258 tmpsfi->sp = sfi->sp;
259 tmpsfi->ra = sfi->ra;
260 tmpsfi->xpc = sfi->xpc;
262 /* Set the previous stackframe info of the temporary one to the
263 next in the chain. */
265 tmpsfi->prev = sfi->prev;
268 if (opt_DebugStackTrace)
269 log_println("[stacktrace fill]");
274 /* stacktrace_stackframeinfo_next **********************************************
276 Walk the stack (or the stackframeinfo-chain) to the next method and
277 return the new stackframe values in the temporary stackframeinfo
280 ATTENTION: This function does NOT skip builtin methods!
283 tmpsfi ... temporary stackframeinfo of current method
285 *******************************************************************************/
287 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
295 stackframeinfo_t *prevsfi;
299 assert(tmpsfi != NULL);
301 /* Get values from the stackframeinfo. */
309 /* Get the current stack frame size. */
311 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
313 /* Get the RA of the current stack frame (RA to the parent Java
314 method) if the current method is a non-leaf method. Otherwise
315 the value in the stackframeinfo is correct (from the signal
318 #if defined(ENABLE_JIT)
319 # if defined(ENABLE_INTRP)
321 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
325 if (!code_is_leafmethod(code))
326 ra = md_stacktrace_get_returnaddress(sp, framesize);
329 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
332 /* Get the PV for the parent Java method. */
334 #if defined(ENABLE_INTRP)
336 pv = methodtree_find(ra);
340 #if defined(ENABLE_JIT)
341 # if defined(__SPARC_64__)
342 sp = md_get_framepointer(sp);
343 pv = md_get_pv_from_stackframe(sp);
345 pv = md_codegen_get_pv_from_pc(ra);
350 /* Get the codeinfo pointer for the parent Java method. */
352 code = code_get_codeinfo_for_pv(pv);
354 /* Calculate the SP for the parent Java method. */
356 #if defined(ENABLE_INTRP)
358 sp = *(u1 **) (sp - framesize);
362 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
363 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
364 #elif defined(__SPARC_64__)
365 /* already has the new sp */
367 sp = (void *) (((intptr_t) sp) + framesize);
371 /* If the new codeinfo pointer is NULL we reached a
372 asm_vm_call_method function. In this case we get the next
373 values from the previous stackframeinfo in the chain.
374 Otherwise the new values have been calculated before. */
377 prevsfi = tmpsfi->prev;
379 /* If the previous stackframeinfo in the chain is NULL we
380 reached the top of the stacktrace. We set code and prev to
381 NULL to mark the end, which is checked in
382 stacktrace_stackframeinfo_end_check. */
384 if (prevsfi == NULL) {
390 /* Fill the temporary stackframeinfo with the new values. */
392 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
395 /* Store the new values in the stackframeinfo. NOTE: We
396 subtract 1 from the RA to get the XPC, because the RA
397 points to the instruction after the call instruction. */
403 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
407 /* Print current method information. */
409 if (opt_DebugStackTrace) {
411 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
412 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
414 method_print(tmpsfi->code->m);
422 /* stacktrace_stackframeinfo_end_check *****************************************
424 Check if we reached the end of the stacktrace.
427 tmpsfi ... temporary stackframeinfo of current method
430 true .... the end is reached
431 false ... the end is not reached
433 *******************************************************************************/
435 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
439 assert(tmpsfi != NULL);
441 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
443 if (opt_DebugStackTrace)
444 log_println("[stacktrace stop]");
454 /* stacktrace_depth ************************************************************
456 Calculates and returns the depth of the current stacktrace.
459 sfi ... stackframeinfo where to start the stacktrace
462 depth of the stacktrace
464 *******************************************************************************/
466 static int stacktrace_depth(stackframeinfo_t *sfi)
468 stackframeinfo_t tmpsfi;
473 if (opt_DebugStackTrace)
474 log_println("[stacktrace_depth]");
477 /* XXX This is not correct, but a workaround for threads-dump for
479 /* assert(sfi != NULL); */
483 /* Iterate over all stackframes. */
487 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
488 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
489 stacktrace_stackframeinfo_next(&tmpsfi)) {
490 /* Get methodinfo. */
494 /* Skip builtin methods. */
496 if (m->flags & ACC_METHOD_BUILTIN)
506 /* stacktrace_get **************************************************************
508 Builds and returns a stacktrace starting from the given stackframe
509 info and returns the stacktrace structure wrapped in a Java
510 byte-array to not confuse the GC.
513 sfi ... stackframe info to start stacktrace from
516 stacktrace as Java byte-array
518 *******************************************************************************/
520 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
522 stackframeinfo_t tmpsfi;
524 java_handle_bytearray_t *ba;
527 stacktrace_entry_t *ste;
529 bool skip_fillInStackTrace;
532 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
535 if (opt_DebugStackTrace)
536 log_println("[stacktrace_get]");
539 skip_fillInStackTrace = true;
542 depth = stacktrace_depth(sfi);
547 /* Allocate memory from the GC heap and copy the stacktrace
549 /* ATTENTION: Use a Java byte-array for this to not confuse the
551 /* FIXME: We waste some memory here as we skip some entries
554 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
556 ba = builtin_newarray_byte(ba_size);
561 /* Get a stacktrace entry pointer. */
562 /* ATTENTION: We need a critical section here because we use the
563 byte-array data pointer directly. */
567 st = (stacktrace_t *) LLNI_array_data(ba);
571 /* Iterate over the whole stack. */
573 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
574 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
575 stacktrace_stackframeinfo_next(&tmpsfi)) {
576 /* Get the methodinfo. */
580 /* Skip builtin methods. */
582 if (m->flags & ACC_METHOD_BUILTIN)
585 /* This logic is taken from
586 hotspot/src/share/vm/classfile/javaClasses.cpp
587 (java_lang_Throwable::fill_in_stack_trace). */
589 if (skip_fillInStackTrace == true) {
590 /* Check "fillInStackTrace" only once, so we negate the
591 flag after the first time check. */
593 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
594 /* For GNU Classpath we also need to skip
595 VMThrowable.fillInStackTrace(). */
597 if ((m->clazz == class_java_lang_VMThrowable) &&
598 (m->name == utf_fillInStackTrace))
602 skip_fillInStackTrace = false;
604 if (m->name == utf_fillInStackTrace)
608 /* Skip <init> methods of the exceptions klass. If there is
609 <init> methods that belongs to a superclass of the
610 exception we are going to skipping them in stack trace. */
612 if (skip_init == true) {
613 if ((m->name == utf_init) &&
614 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
618 /* If no "Throwable.init()" method found, we stop
619 checking it next time. */
625 /* Store the stacktrace entry and increment the pointer. */
627 ste->code = tmpsfi.code;
628 ste->pc = tmpsfi.xpc;
633 /* Store the number of entries in the stacktrace structure. */
635 st->length = ste - st->entries;
639 /* release dump memory */
641 /* dump_release(dumpsize); */
643 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
648 /* dump_release(dumpsize); */
650 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
657 /* stacktrace_get_current ******************************************************
659 Builds and returns a stacktrace from the current thread and returns
660 the stacktrace structure wrapped in a Java byte-array to not
664 stacktrace as Java byte-array
666 *******************************************************************************/
668 java_handle_bytearray_t *stacktrace_get_current(void)
670 stackframeinfo_t *sfi;
671 java_handle_bytearray_t *ba;
673 sfi = threads_get_current_stackframeinfo();
674 ba = stacktrace_get(sfi);
680 /* stacktrace_get_caller_class *************************************************
682 Get the class on the stack at the given depth. This function skips
683 various special classes or methods.
686 depth ... depth to get caller class of
691 *******************************************************************************/
693 #if defined(ENABLE_JAVASE)
694 classinfo *stacktrace_get_caller_class(int depth)
696 stackframeinfo_t *sfi;
697 stackframeinfo_t tmpsfi;
703 if (opt_DebugStackTrace)
704 log_println("[stacktrace_get_caller_class]");
707 /* Get the stackframeinfo of the current thread. */
709 sfi = threads_get_current_stackframeinfo();
711 /* Iterate over the whole stack until we reached the requested
716 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
717 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
718 stacktrace_stackframeinfo_next(&tmpsfi)) {
723 /* Skip builtin methods. */
725 if (m->flags & ACC_METHOD_BUILTIN)
728 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
729 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
730 (vframeStreamCommon::security_get_caller_frame). */
732 /* This is java.lang.reflect.Method.invoke(), skip it. */
734 if (m == method_java_lang_reflect_Method_invoke)
737 /* This is an auxiliary frame, skip it. */
739 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
743 /* We reached the requested depth. */
756 /* stacktrace_first_nonnull_classloader ****************************************
758 Returns the first non-null (user-defined) classloader on the stack.
759 If none is found NULL is returned.
764 *******************************************************************************/
766 classloader_t *stacktrace_first_nonnull_classloader(void)
768 stackframeinfo_t *sfi;
769 stackframeinfo_t tmpsfi;
774 if (opt_DebugStackTrace)
775 log_println("[stacktrace_first_nonnull_classloader]");
778 /* Get the stackframeinfo of the current thread. */
780 sfi = threads_get_current_stackframeinfo();
782 /* Iterate over the whole stack. */
784 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
785 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
786 stacktrace_stackframeinfo_next(&tmpsfi)) {
789 cl = class_get_classloader(m->clazz);
799 /* stacktrace_getClassContext **************************************************
801 Creates a Class context array.
804 the array of java.lang.Class objects, or
805 NULL if an exception has been thrown
807 *******************************************************************************/
809 java_handle_objectarray_t *stacktrace_getClassContext(void)
811 stackframeinfo_t *sfi;
812 stackframeinfo_t tmpsfi;
814 java_handle_objectarray_t *oa;
815 java_object_t **data;
819 CYCLES_STATS_DECLARE_AND_START
822 if (opt_DebugStackTrace)
823 log_println("[stacktrace_getClassContext]");
826 sfi = threads_get_current_stackframeinfo();
828 /* Get the depth of the current stack. */
830 depth = stacktrace_depth(sfi);
832 /* The first stackframe corresponds to the method whose
833 implementation calls this native function. We remove that
837 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
838 stacktrace_stackframeinfo_next(&tmpsfi);
840 /* Allocate the Class array. */
842 oa = builtin_anewarray(depth, class_java_lang_Class);
845 CYCLES_STATS_END(stacktrace_getClassContext);
850 /* Fill the Class array from the stacktrace list. */
854 data = LLNI_array_data(oa);
856 /* Iterate over the whole stack. */
861 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
862 stacktrace_stackframeinfo_next(&tmpsfi)) {
863 /* Get methodinfo. */
867 /* Skip builtin methods. */
869 if (m->flags & ACC_METHOD_BUILTIN)
872 /* Store the class in the array. */
874 data[i] = (java_object_t *) m->clazz;
881 CYCLES_STATS_END(stacktrace_getClassContext)
887 /* stacktrace_getCurrentClass **************************************************
889 Find the current class by walking the stack trace.
891 Quote from the JNI documentation:
893 In the Java 2 Platform, FindClass locates the class loader
894 associated with the current native method. If the native code
895 belongs to a system class, no class loader will be
896 involved. Otherwise, the proper class loader will be invoked to
897 load and link the named class. When FindClass is called through the
898 Invocation Interface, there is no current native method or its
899 associated class loader. In that case, the result of
900 ClassLoader.getBaseClassLoader is used."
902 *******************************************************************************/
904 #if defined(ENABLE_JAVASE)
905 classinfo *stacktrace_get_current_class(void)
907 stackframeinfo_t *sfi;
908 stackframeinfo_t tmpsfi;
911 CYCLES_STATS_DECLARE_AND_START;
914 if (opt_DebugStackTrace)
915 log_println("[stacktrace_get_current_class]");
918 /* Get the stackframeinfo of the current thread. */
920 sfi = threads_get_current_stackframeinfo();
922 /* If the stackframeinfo is NULL then FindClass is called through
923 the Invocation Interface and we return NULL */
926 CYCLES_STATS_END(stacktrace_getCurrentClass);
931 /* Iterate over the whole stack. */
933 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
934 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
935 stacktrace_stackframeinfo_next(&tmpsfi)) {
936 /* Get the methodinfo. */
940 if (m->clazz == class_java_security_PrivilegedAction) {
941 CYCLES_STATS_END(stacktrace_getCurrentClass);
946 if (m->clazz != NULL) {
947 CYCLES_STATS_END(stacktrace_getCurrentClass);
953 /* No Java method found on the stack. */
955 CYCLES_STATS_END(stacktrace_getCurrentClass);
959 #endif /* ENABLE_JAVASE */
962 /* stacktrace_get_stack ********************************************************
964 Create a 2-dimensional array for java.security.VMAccessControler.
968 NULL if an exception has been thrown
970 *******************************************************************************/
972 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
973 java_handle_objectarray_t *stacktrace_get_stack(void)
975 stackframeinfo_t *sfi;
976 stackframeinfo_t tmpsfi;
978 java_handle_objectarray_t *oa;
979 java_handle_objectarray_t *classes;
980 java_handle_objectarray_t *methodnames;
982 java_handle_t *string;
985 CYCLES_STATS_DECLARE_AND_START
988 if (opt_DebugStackTrace)
989 log_println("[stacktrace_get_stack]");
992 /* Get the stackframeinfo of the current thread. */
994 sfi = threads_get_current_stackframeinfo();
996 /* Get the depth of the current stack. */
998 depth = stacktrace_depth(sfi);
1003 /* Allocate the required arrays. */
1005 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1010 classes = builtin_anewarray(depth, class_java_lang_Class);
1012 if (classes == NULL)
1015 methodnames = builtin_anewarray(depth, class_java_lang_String);
1017 if (methodnames == NULL)
1020 /* Set up the 2-dimensional array. */
1022 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1023 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1025 /* Iterate over the whole stack. */
1026 /* TODO We should use a critical section here to speed things
1031 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1032 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1033 stacktrace_stackframeinfo_next(&tmpsfi)) {
1034 /* Get the methodinfo. */
1038 /* Skip builtin methods. */
1040 if (m->flags & ACC_METHOD_BUILTIN)
1043 /* Store the class in the array. */
1044 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1047 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1049 /* Store the name in the array. */
1051 string = javastring_new(m->name);
1056 array_objectarray_element_set(methodnames, i, string);
1061 CYCLES_STATS_END(stacktrace_get_stack)
1066 CYCLES_STATS_END(stacktrace_get_stack)
1073 /* stacktrace_print_entry ****************************************************
1075 Print line for a stacktrace entry.
1078 m ............ methodinfo of the entry
1079 linenumber ... linenumber of the entry
1081 *******************************************************************************/
1083 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1091 if (m->flags & ACC_METHOD_BUILTIN)
1094 utf_display_printable_ascii_classname(m->clazz->name);
1097 utf_display_printable_ascii(m->name);
1098 utf_display_printable_ascii(m->descriptor);
1100 if (m->flags & ACC_NATIVE) {
1101 puts("(Native Method)");
1104 if (m->flags & ACC_METHOD_BUILTIN) {
1109 utf_display_printable_ascii(m->clazz->sourcefile);
1110 printf(":%d)\n", linenumber);
1118 /* stacktrace_print ************************************************************
1120 Print the given stacktrace with CACAO intern methods only (no Java
1123 This method is used by stacktrace_dump_trace and
1124 builtin_trace_exception.
1127 st ... stacktrace to print
1129 *******************************************************************************/
1131 void stacktrace_print(stacktrace_t *st)
1133 stacktrace_entry_t *ste;
1138 ste = &(st->entries[0]);
1140 for (i = 0; i < st->length; i++, ste++) {
1143 /* Get the line number. */
1145 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1147 stacktrace_print_entry(m, linenumber);
1152 /* stacktrace_print_current ****************************************************
1154 Print the current stacktrace of the current thread.
1156 NOTE: This function prints all frames of the stacktrace and does
1157 not skip frames like stacktrace_get.
1159 *******************************************************************************/
1161 void stacktrace_print_current(void)
1163 stackframeinfo_t *sfi;
1164 stackframeinfo_t tmpsfi;
1169 sfi = threads_get_current_stackframeinfo();
1172 puts("\t<<No stacktrace available>>");
1177 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1178 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1179 stacktrace_stackframeinfo_next(&tmpsfi)) {
1180 /* Get the methodinfo. */
1185 /* Get the line number. */
1187 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1189 stacktrace_print_entry(m, linenumber);
1194 /* stacktrace_print_of_thread **************************************************
1196 Print the current stacktrace of the given thread.
1201 *******************************************************************************/
1203 #if defined(ENABLE_THREADS)
1204 void stacktrace_print_of_thread(threadobject *t)
1206 stackframeinfo_t *sfi;
1207 stackframeinfo_t tmpsfi;
1212 /* Build a stacktrace for the passed thread. */
1214 sfi = t->_stackframeinfo;
1217 puts("\t<<No stacktrace available>>");
1222 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1223 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1224 stacktrace_stackframeinfo_next(&tmpsfi)) {
1225 /* Get the methodinfo. */
1230 /* Get the line number. */
1232 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1234 stacktrace_print_entry(m, linenumber);
1240 /* stacktrace_print_exception **************************************************
1242 Print the stacktrace of a given exception (more or less a wrapper
1243 to stacktrace_print).
1246 h ... handle of exception to print
1248 *******************************************************************************/
1250 void stacktrace_print_exception(java_handle_t *h)
1255 java_lang_Throwable t(h);
1257 /* now print the stacktrace */
1259 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1261 java_lang_VMThrowable vmt(t.get_vmState());
1262 java_handle_bytearray_t* backtrace = vmt.get_vmdata();
1264 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1266 java_handle_bytearray_t* backtrace = t.get_backtrace();
1269 # error unknown classpath configuration
1274 assert(backtrace != NULL);
1276 /* We need a critical section here as we use the byte-array data
1277 pointer directly. */
1279 LLNI_CRITICAL_START;
1281 stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
1283 stacktrace_print(st);
1289 #if defined(ENABLE_CYCLES_STATS)
1290 void stacktrace_print_cycles_stats(FILE *file)
1292 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1293 CYCLES_STATS_PRINT(stacktrace_get, file);
1294 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1295 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1296 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1304 * These are local overrides for various environment variables in Emacs.
1305 * Please do not remove this and leave it at the end of the file, where
1306 * Emacs will automagically detect them.
1307 * ---------------------------------------------------------------------
1310 * indent-tabs-mode: t
1314 * vim:noexpandtab:sw=4:ts=4: