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 "native/llni.h"
44 #include "threads/thread.hpp"
46 #include "toolbox/logging.h"
48 #include "vm/array.hpp"
49 #include "vm/jit/builtin.hpp"
50 #include "vm/class.hpp"
51 #include "vm/cycles-stats.h"
52 #include "vm/exceptions.hpp"
53 #include "vm/globals.hpp"
54 #include "vm/javaobjects.hpp"
55 #include "vm/loader.hpp"
56 #include "vm/method.h"
57 #include "vm/options.h"
58 #include "vm/string.hpp"
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/codegen-common.hpp"
63 #include "vm/jit/linenumbertable.hpp"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/methodtree.h"
68 // FIXME Use C-linkage for now.
71 /* global variables ***********************************************************/
73 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
74 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
75 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
76 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
77 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
78 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
81 /* stacktrace_stackframeinfo_add ***********************************************
83 Fills a stackframe info structure with the given or calculated
84 values and adds it to the chain.
86 *******************************************************************************/
88 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
90 stackframeinfo_t *currentsfi;
92 #if defined(ENABLE_JIT)
96 /* Get current stackframe info. */
98 currentsfi = threads_get_current_stackframeinfo();
100 /* sometimes we don't have pv handy (e.g. in asmpart.S:
101 L_asm_call_jit_compiler_exception or in the interpreter). */
104 #if defined(ENABLE_INTRP)
106 pv = methodtree_find(ra);
110 #if defined(ENABLE_JIT)
111 # if defined(__SPARC_64__)
112 pv = md_get_pv_from_stackframe(sp);
114 pv = md_codegen_get_pv_from_pc(ra);
120 /* Get codeinfo pointer for the parent Java method. */
122 code = code_get_codeinfo_for_pv(pv);
125 /* assert(m != NULL); */
127 #if defined(ENABLE_JIT)
128 # if defined(ENABLE_INTRP)
129 /* When using the interpreter, we pass RA to the function. */
133 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
134 /* On i386 and x86_64 we always have to get the return address
136 /* m68k has return address on stack always */
137 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
138 the RA from stack. */
140 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
142 ra = md_stacktrace_get_returnaddress(sp, framesize);
144 /* If the method is a non-leaf function, we need to get the
145 return address from the stack. For leaf functions the
146 return address is set correctly. This makes the assembler
147 and the signal handler code simpler. The code is NULL is
148 the asm_vm_call_method special case. */
150 if ((code == NULL) || !code_is_leafmethod(code)) {
151 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
153 ra = md_stacktrace_get_returnaddress(sp, framesize);
156 # if defined(ENABLE_INTRP)
161 /* Calculate XPC when not given. The XPC is then the return
162 address of the current method minus 1 because the RA points to
163 the instruction after the call instruction. This is required
164 e.g. for method stubs. */
167 xpc = (void *) (((intptr_t) ra) - 1);
170 /* Fill new stackframeinfo structure. */
172 sfi->prev = currentsfi;
180 if (opt_DebugStackFrameInfo) {
182 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
183 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
184 method_print(sfi->code->m);
190 /* Store new stackframeinfo pointer. */
192 threads_set_current_stackframeinfo(sfi);
194 /* set the native world flag for the current thread */
195 /* ATTENTION: This flag tells the GC how to treat this thread in case of
196 a collection. Set this flag _after_ a valid stackframe info was set. */
198 THREAD_NATIVEWORLD_ENTER;
202 /* stacktrace_stackframeinfo_remove ********************************************
204 Remove the given stackframeinfo from the chain in the current
207 *******************************************************************************/
209 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
211 /* Clear the native world flag for the current thread. */
212 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
214 THREAD_NATIVEWORLD_EXIT;
217 if (opt_DebugStackFrameInfo) {
219 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
220 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
221 method_print(sfi->code->m);
227 /* Set previous stackframe info. */
229 threads_set_current_stackframeinfo(sfi->prev);
233 /* stacktrace_stackframeinfo_fill **********************************************
235 Fill the temporary stackframeinfo structure with the values given
239 tmpsfi ... temporary stackframeinfo
240 sfi ...... stackframeinfo to be used in the next iteration
242 *******************************************************************************/
244 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
248 assert(tmpsfi != NULL);
251 /* Fill the temporary stackframeinfo. */
253 tmpsfi->code = sfi->code;
254 tmpsfi->pv = sfi->pv;
255 tmpsfi->sp = sfi->sp;
256 tmpsfi->ra = sfi->ra;
257 tmpsfi->xpc = sfi->xpc;
259 /* Set the previous stackframe info of the temporary one to the
260 next in the chain. */
262 tmpsfi->prev = sfi->prev;
265 if (opt_DebugStackTrace)
266 log_println("[stacktrace fill]");
271 /* stacktrace_stackframeinfo_next **********************************************
273 Walk the stack (or the stackframeinfo-chain) to the next method and
274 return the new stackframe values in the temporary stackframeinfo
277 ATTENTION: This function does NOT skip builtin methods!
280 tmpsfi ... temporary stackframeinfo of current method
282 *******************************************************************************/
284 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
292 stackframeinfo_t *prevsfi;
296 assert(tmpsfi != NULL);
298 /* Get values from the stackframeinfo. */
306 /* Get the current stack frame size. */
308 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
310 /* Get the RA of the current stack frame (RA to the parent Java
311 method) if the current method is a non-leaf method. Otherwise
312 the value in the stackframeinfo is correct (from the signal
315 #if defined(ENABLE_JIT)
316 # if defined(ENABLE_INTRP)
318 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
322 if (!code_is_leafmethod(code))
323 ra = md_stacktrace_get_returnaddress(sp, framesize);
326 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
329 /* Get the PV for the parent Java method. */
331 #if defined(ENABLE_INTRP)
333 pv = methodtree_find(ra);
337 #if defined(ENABLE_JIT)
338 # if defined(__SPARC_64__)
339 sp = md_get_framepointer(sp);
340 pv = md_get_pv_from_stackframe(sp);
342 pv = md_codegen_get_pv_from_pc(ra);
347 /* Get the codeinfo pointer for the parent Java method. */
349 code = code_get_codeinfo_for_pv(pv);
351 /* Calculate the SP for the parent Java method. */
353 #if defined(ENABLE_INTRP)
355 sp = *(u1 **) (sp - framesize);
359 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
360 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
361 #elif defined(__SPARC_64__)
362 /* already has the new sp */
364 sp = (void *) (((intptr_t) sp) + framesize);
368 /* If the new codeinfo pointer is NULL we reached a
369 asm_vm_call_method function. In this case we get the next
370 values from the previous stackframeinfo in the chain.
371 Otherwise the new values have been calculated before. */
374 prevsfi = tmpsfi->prev;
376 /* If the previous stackframeinfo in the chain is NULL we
377 reached the top of the stacktrace. We set code and prev to
378 NULL to mark the end, which is checked in
379 stacktrace_stackframeinfo_end_check. */
381 if (prevsfi == NULL) {
387 /* Fill the temporary stackframeinfo with the new values. */
389 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
392 /* Store the new values in the stackframeinfo. NOTE: We
393 subtract 1 from the RA to get the XPC, because the RA
394 points to the instruction after the call instruction. */
400 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
404 /* Print current method information. */
406 if (opt_DebugStackTrace) {
408 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
409 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
411 method_print(tmpsfi->code->m);
419 /* stacktrace_stackframeinfo_end_check *****************************************
421 Check if we reached the end of the stacktrace.
424 tmpsfi ... temporary stackframeinfo of current method
427 true .... the end is reached
428 false ... the end is not reached
430 *******************************************************************************/
432 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
436 assert(tmpsfi != NULL);
438 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
440 if (opt_DebugStackTrace)
441 log_println("[stacktrace stop]");
451 /* stacktrace_depth ************************************************************
453 Calculates and returns the depth of the current stacktrace.
456 sfi ... stackframeinfo where to start the stacktrace
459 depth of the stacktrace
461 *******************************************************************************/
463 static int stacktrace_depth(stackframeinfo_t *sfi)
465 stackframeinfo_t tmpsfi;
470 if (opt_DebugStackTrace)
471 log_println("[stacktrace_depth]");
474 /* XXX This is not correct, but a workaround for threads-dump for
476 /* assert(sfi != NULL); */
480 /* Iterate over all stackframes. */
484 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
485 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
486 stacktrace_stackframeinfo_next(&tmpsfi)) {
487 /* Get methodinfo. */
491 /* Skip builtin methods. */
493 if (m->flags & ACC_METHOD_BUILTIN)
503 /* stacktrace_get **************************************************************
505 Builds and returns a stacktrace starting from the given stackframe
506 info and returns the stacktrace structure wrapped in a Java
507 byte-array to not confuse the GC.
510 sfi ... stackframe info to start stacktrace from
513 stacktrace as Java byte-array
515 *******************************************************************************/
517 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
519 stackframeinfo_t tmpsfi;
521 java_handle_bytearray_t *ba;
524 stacktrace_entry_t *ste;
526 bool skip_fillInStackTrace;
529 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
532 if (opt_DebugStackTrace)
533 log_println("[stacktrace_get]");
536 skip_fillInStackTrace = true;
539 depth = stacktrace_depth(sfi);
544 /* Allocate memory from the GC heap and copy the stacktrace
546 /* ATTENTION: Use a Java byte-array for this to not confuse the
548 /* FIXME: We waste some memory here as we skip some entries
551 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
553 ba = builtin_newarray_byte(ba_size);
558 /* Get a stacktrace entry pointer. */
559 /* ATTENTION: We need a critical section here because we use the
560 byte-array data pointer directly. */
564 st = (stacktrace_t *) LLNI_array_data(ba);
568 /* Iterate over the whole stack. */
570 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
571 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
572 stacktrace_stackframeinfo_next(&tmpsfi)) {
573 /* Get the methodinfo. */
577 /* Skip builtin methods. */
579 if (m->flags & ACC_METHOD_BUILTIN)
582 /* This logic is taken from
583 hotspot/src/share/vm/classfile/javaClasses.cpp
584 (java_lang_Throwable::fill_in_stack_trace). */
586 if (skip_fillInStackTrace == true) {
587 /* Check "fillInStackTrace" only once, so we negate the
588 flag after the first time check. */
590 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
591 /* For GNU Classpath we also need to skip
592 VMThrowable.fillInStackTrace(). */
594 if ((m->clazz == class_java_lang_VMThrowable) &&
595 (m->name == utf_fillInStackTrace))
599 skip_fillInStackTrace = false;
601 if (m->name == utf_fillInStackTrace)
605 /* Skip <init> methods of the exceptions klass. If there is
606 <init> methods that belongs to a superclass of the
607 exception we are going to skipping them in stack trace. */
609 if (skip_init == true) {
610 if ((m->name == utf_init) &&
611 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
615 /* If no "Throwable.init()" method found, we stop
616 checking it next time. */
622 /* Store the stacktrace entry and increment the pointer. */
624 ste->code = tmpsfi.code;
625 ste->pc = tmpsfi.xpc;
630 /* Store the number of entries in the stacktrace structure. */
632 st->length = ste - st->entries;
636 /* release dump memory */
638 /* dump_release(dumpsize); */
640 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
645 /* dump_release(dumpsize); */
647 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
654 /* stacktrace_get_current ******************************************************
656 Builds and returns a stacktrace from the current thread and returns
657 the stacktrace structure wrapped in a Java byte-array to not
661 stacktrace as Java byte-array
663 *******************************************************************************/
665 java_handle_bytearray_t *stacktrace_get_current(void)
667 stackframeinfo_t *sfi;
668 java_handle_bytearray_t *ba;
670 sfi = threads_get_current_stackframeinfo();
671 ba = stacktrace_get(sfi);
677 /* stacktrace_get_caller_class *************************************************
679 Get the class on the stack at the given depth. This function skips
680 various special classes or methods.
683 depth ... depth to get caller class of
688 *******************************************************************************/
690 #if defined(ENABLE_JAVASE)
691 classinfo *stacktrace_get_caller_class(int depth)
693 stackframeinfo_t *sfi;
694 stackframeinfo_t tmpsfi;
700 if (opt_DebugStackTrace)
701 log_println("[stacktrace_get_caller_class]");
704 /* Get the stackframeinfo of the current thread. */
706 sfi = threads_get_current_stackframeinfo();
708 /* Iterate over the whole stack until we reached the requested
713 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
714 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
715 stacktrace_stackframeinfo_next(&tmpsfi)) {
720 /* Skip builtin methods. */
722 if (m->flags & ACC_METHOD_BUILTIN)
725 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
726 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
727 (vframeStreamCommon::security_get_caller_frame). */
729 /* This is java.lang.reflect.Method.invoke(), skip it. */
731 if (m == method_java_lang_reflect_Method_invoke)
734 /* This is an auxiliary frame, skip it. */
736 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
740 /* We reached the requested depth. */
753 /* stacktrace_first_nonnull_classloader ****************************************
755 Returns the first non-null (user-defined) classloader on the stack.
756 If none is found NULL is returned.
761 *******************************************************************************/
763 classloader_t *stacktrace_first_nonnull_classloader(void)
765 stackframeinfo_t *sfi;
766 stackframeinfo_t tmpsfi;
771 if (opt_DebugStackTrace)
772 log_println("[stacktrace_first_nonnull_classloader]");
775 /* Get the stackframeinfo of the current thread. */
777 sfi = threads_get_current_stackframeinfo();
779 /* Iterate over the whole stack. */
781 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
782 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
783 stacktrace_stackframeinfo_next(&tmpsfi)) {
786 cl = class_get_classloader(m->clazz);
796 /* stacktrace_getClassContext **************************************************
798 Creates a Class context array.
801 the array of java.lang.Class objects, or
802 NULL if an exception has been thrown
804 *******************************************************************************/
806 java_handle_objectarray_t *stacktrace_getClassContext(void)
808 stackframeinfo_t *sfi;
809 stackframeinfo_t tmpsfi;
811 java_handle_objectarray_t *oa;
812 java_object_t **data;
816 CYCLES_STATS_DECLARE_AND_START
819 if (opt_DebugStackTrace)
820 log_println("[stacktrace_getClassContext]");
823 sfi = threads_get_current_stackframeinfo();
825 /* Get the depth of the current stack. */
827 depth = stacktrace_depth(sfi);
829 /* The first stackframe corresponds to the method whose
830 implementation calls this native function. We remove that
834 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
835 stacktrace_stackframeinfo_next(&tmpsfi);
837 /* Allocate the Class array. */
839 oa = builtin_anewarray(depth, class_java_lang_Class);
842 CYCLES_STATS_END(stacktrace_getClassContext);
847 /* Fill the Class array from the stacktrace list. */
851 data = LLNI_array_data(oa);
853 /* Iterate over the whole stack. */
858 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
859 stacktrace_stackframeinfo_next(&tmpsfi)) {
860 /* Get methodinfo. */
864 /* Skip builtin methods. */
866 if (m->flags & ACC_METHOD_BUILTIN)
869 /* Store the class in the array. */
871 data[i] = (java_object_t *) m->clazz;
878 CYCLES_STATS_END(stacktrace_getClassContext)
884 /* stacktrace_getCurrentClass **************************************************
886 Find the current class by walking the stack trace.
888 Quote from the JNI documentation:
890 In the Java 2 Platform, FindClass locates the class loader
891 associated with the current native method. If the native code
892 belongs to a system class, no class loader will be
893 involved. Otherwise, the proper class loader will be invoked to
894 load and link the named class. When FindClass is called through the
895 Invocation Interface, there is no current native method or its
896 associated class loader. In that case, the result of
897 ClassLoader.getBaseClassLoader is used."
899 *******************************************************************************/
901 #if defined(ENABLE_JAVASE)
902 classinfo *stacktrace_get_current_class(void)
904 stackframeinfo_t *sfi;
905 stackframeinfo_t tmpsfi;
908 CYCLES_STATS_DECLARE_AND_START;
911 if (opt_DebugStackTrace)
912 log_println("[stacktrace_get_current_class]");
915 /* Get the stackframeinfo of the current thread. */
917 sfi = threads_get_current_stackframeinfo();
919 /* If the stackframeinfo is NULL then FindClass is called through
920 the Invocation Interface and we return NULL */
923 CYCLES_STATS_END(stacktrace_getCurrentClass);
928 /* Iterate over the whole stack. */
930 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
931 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
932 stacktrace_stackframeinfo_next(&tmpsfi)) {
933 /* Get the methodinfo. */
937 if (m->clazz == class_java_security_PrivilegedAction) {
938 CYCLES_STATS_END(stacktrace_getCurrentClass);
943 if (m->clazz != NULL) {
944 CYCLES_STATS_END(stacktrace_getCurrentClass);
950 /* No Java method found on the stack. */
952 CYCLES_STATS_END(stacktrace_getCurrentClass);
956 #endif /* ENABLE_JAVASE */
959 /* stacktrace_get_stack ********************************************************
961 Create a 2-dimensional array for java.security.VMAccessControler.
965 NULL if an exception has been thrown
967 *******************************************************************************/
969 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
970 java_handle_objectarray_t *stacktrace_get_stack(void)
972 stackframeinfo_t *sfi;
973 stackframeinfo_t tmpsfi;
975 java_handle_objectarray_t *oa;
976 java_handle_objectarray_t *classes;
977 java_handle_objectarray_t *methodnames;
979 java_handle_t *string;
982 CYCLES_STATS_DECLARE_AND_START
985 if (opt_DebugStackTrace)
986 log_println("[stacktrace_get_stack]");
989 /* Get the stackframeinfo of the current thread. */
991 sfi = threads_get_current_stackframeinfo();
993 /* Get the depth of the current stack. */
995 depth = stacktrace_depth(sfi);
1000 /* Allocate the required arrays. */
1002 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1007 classes = builtin_anewarray(depth, class_java_lang_Class);
1009 if (classes == NULL)
1012 methodnames = builtin_anewarray(depth, class_java_lang_String);
1014 if (methodnames == NULL)
1017 /* Set up the 2-dimensional array. */
1019 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1020 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1022 /* Iterate over the whole stack. */
1023 /* TODO We should use a critical section here to speed things
1028 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1029 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1030 stacktrace_stackframeinfo_next(&tmpsfi)) {
1031 /* Get the methodinfo. */
1035 /* Skip builtin methods. */
1037 if (m->flags & ACC_METHOD_BUILTIN)
1040 /* Store the class in the array. */
1041 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1044 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1046 /* Store the name in the array. */
1048 string = javastring_new(m->name);
1053 array_objectarray_element_set(methodnames, i, string);
1058 CYCLES_STATS_END(stacktrace_get_stack)
1063 CYCLES_STATS_END(stacktrace_get_stack)
1070 /* stacktrace_print_entry ****************************************************
1072 Print line for a stacktrace entry.
1075 m ............ methodinfo of the entry
1076 linenumber ... linenumber of the entry
1078 *******************************************************************************/
1080 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1088 if (m->flags & ACC_METHOD_BUILTIN)
1091 utf_display_printable_ascii_classname(m->clazz->name);
1094 utf_display_printable_ascii(m->name);
1095 utf_display_printable_ascii(m->descriptor);
1097 if (m->flags & ACC_NATIVE) {
1098 puts("(Native Method)");
1101 if (m->flags & ACC_METHOD_BUILTIN) {
1106 utf_display_printable_ascii(m->clazz->sourcefile);
1107 printf(":%d)\n", linenumber);
1115 /* stacktrace_print ************************************************************
1117 Print the given stacktrace with CACAO intern methods only (no Java
1120 This method is used by stacktrace_dump_trace and
1121 builtin_trace_exception.
1124 st ... stacktrace to print
1126 *******************************************************************************/
1128 void stacktrace_print(stacktrace_t *st)
1130 stacktrace_entry_t *ste;
1135 ste = &(st->entries[0]);
1137 for (i = 0; i < st->length; i++, ste++) {
1140 /* Get the line number. */
1142 linenumber = ste->code->linenumbertable->find(&m, ste->pc);
1144 stacktrace_print_entry(m, linenumber);
1149 /* stacktrace_print_current ****************************************************
1151 Print the current stacktrace of the current thread.
1153 NOTE: This function prints all frames of the stacktrace and does
1154 not skip frames like stacktrace_get.
1156 *******************************************************************************/
1158 void stacktrace_print_current(void)
1160 stackframeinfo_t *sfi;
1161 stackframeinfo_t tmpsfi;
1166 sfi = threads_get_current_stackframeinfo();
1169 puts("\t<<No stacktrace available>>");
1174 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1175 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1176 stacktrace_stackframeinfo_next(&tmpsfi)) {
1177 /* Get the methodinfo. */
1182 // Get the line number.
1183 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1185 stacktrace_print_entry(m, linenumber);
1190 /* stacktrace_print_of_thread **************************************************
1192 Print the current stacktrace of the given thread.
1197 *******************************************************************************/
1199 #if defined(ENABLE_THREADS)
1200 void stacktrace_print_of_thread(threadobject *t)
1202 stackframeinfo_t *sfi;
1203 stackframeinfo_t tmpsfi;
1208 /* Build a stacktrace for the passed thread. */
1210 sfi = t->_stackframeinfo;
1213 puts("\t<<No stacktrace available>>");
1218 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1219 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1220 stacktrace_stackframeinfo_next(&tmpsfi)) {
1221 /* Get the methodinfo. */
1226 // Get the line number.
1227 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1229 stacktrace_print_entry(m, linenumber);
1235 /* stacktrace_print_exception **************************************************
1237 Print the stacktrace of a given exception (more or less a wrapper
1238 to stacktrace_print).
1241 h ... handle of exception to print
1243 *******************************************************************************/
1245 void stacktrace_print_exception(java_handle_t *h)
1250 java_lang_Throwable t(h);
1252 /* now print the stacktrace */
1254 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1256 java_lang_VMThrowable vmt(t.get_vmState());
1257 java_handle_bytearray_t* backtrace = vmt.get_vmdata();
1259 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1261 java_handle_bytearray_t* backtrace = t.get_backtrace();
1264 # error unknown classpath configuration
1269 assert(backtrace != NULL);
1271 /* We need a critical section here as we use the byte-array data
1272 pointer directly. */
1274 LLNI_CRITICAL_START;
1276 stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
1278 stacktrace_print(st);
1284 #if defined(ENABLE_CYCLES_STATS)
1285 void stacktrace_print_cycles_stats(FILE *file)
1287 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1288 CYCLES_STATS_PRINT(stacktrace_get, file);
1289 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1290 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1291 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1299 * These are local overrides for various environment variables in Emacs.
1300 * Please do not remove this and leave it at the end of the file, where
1301 * Emacs will automagically detect them.
1302 * ---------------------------------------------------------------------
1305 * indent-tabs-mode: t
1309 * vim:noexpandtab:sw=4:ts=4: