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"
53 #include "vm/cycles-stats.h"
54 #include "vm/exceptions.hpp"
55 #include "vm/globals.hpp"
56 #include "vm/javaobjects.hpp"
57 #include "vm/loader.h"
58 #include "vm/method.h"
59 #include "vm/options.h"
60 #include "vm/string.hpp"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/linenumbertable.h"
66 #include "vm/jit/methodheader.h"
67 #include "vm/jit/methodtree.h"
70 // FIXME Use C-linkage for now.
73 /* global variables ***********************************************************/
75 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
76 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
77 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
78 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
79 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
80 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
83 /* stacktrace_stackframeinfo_add ***********************************************
85 Fills a stackframe info structure with the given or calculated
86 values and adds it to the chain.
88 *******************************************************************************/
90 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
92 stackframeinfo_t *currentsfi;
94 #if defined(ENABLE_JIT)
98 /* Get current stackframe info. */
100 currentsfi = threads_get_current_stackframeinfo();
102 /* sometimes we don't have pv handy (e.g. in asmpart.S:
103 L_asm_call_jit_compiler_exception or in the interpreter). */
106 #if defined(ENABLE_INTRP)
108 pv = methodtree_find(ra);
112 #if defined(ENABLE_JIT)
113 # if defined(__SPARC_64__)
114 pv = md_get_pv_from_stackframe(sp);
116 pv = md_codegen_get_pv_from_pc(ra);
122 /* Get codeinfo pointer for the parent Java method. */
124 code = code_get_codeinfo_for_pv(pv);
127 /* assert(m != NULL); */
129 #if defined(ENABLE_JIT)
130 # if defined(ENABLE_INTRP)
131 /* When using the interpreter, we pass RA to the function. */
135 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
136 /* On i386 and x86_64 we always have to get the return address
138 /* m68k has return address on stack always */
139 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
140 the RA from stack. */
142 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
144 ra = md_stacktrace_get_returnaddress(sp, framesize);
146 /* If the method is a non-leaf function, we need to get the
147 return address from the stack. For leaf functions the
148 return address is set correctly. This makes the assembler
149 and the signal handler code simpler. The code is NULL is
150 the asm_vm_call_method special case. */
152 if ((code == NULL) || !code_is_leafmethod(code)) {
153 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
155 ra = md_stacktrace_get_returnaddress(sp, framesize);
158 # if defined(ENABLE_INTRP)
163 /* Calculate XPC when not given. The XPC is then the return
164 address of the current method minus 1 because the RA points to
165 the instruction after the call instruction. This is required
166 e.g. for method stubs. */
169 xpc = (void *) (((intptr_t) ra) - 1);
172 /* Fill new stackframeinfo structure. */
174 sfi->prev = currentsfi;
182 if (opt_DebugStackFrameInfo) {
184 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
185 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
186 method_print(sfi->code->m);
192 /* Store new stackframeinfo pointer. */
194 threads_set_current_stackframeinfo(sfi);
196 /* set the native world flag for the current thread */
197 /* ATTENTION: This flag tells the GC how to treat this thread in case of
198 a collection. Set this flag _after_ a valid stackframe info was set. */
200 THREAD_NATIVEWORLD_ENTER;
204 /* stacktrace_stackframeinfo_remove ********************************************
206 Remove the given stackframeinfo from the chain in the current
209 *******************************************************************************/
211 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
213 /* Clear the native world flag for the current thread. */
214 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
216 THREAD_NATIVEWORLD_EXIT;
219 if (opt_DebugStackFrameInfo) {
221 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
222 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
223 method_print(sfi->code->m);
229 /* Set previous stackframe info. */
231 threads_set_current_stackframeinfo(sfi->prev);
235 /* stacktrace_stackframeinfo_fill **********************************************
237 Fill the temporary stackframeinfo structure with the values given
241 tmpsfi ... temporary stackframeinfo
242 sfi ...... stackframeinfo to be used in the next iteration
244 *******************************************************************************/
246 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
250 assert(tmpsfi != NULL);
253 /* Fill the temporary stackframeinfo. */
255 tmpsfi->code = sfi->code;
256 tmpsfi->pv = sfi->pv;
257 tmpsfi->sp = sfi->sp;
258 tmpsfi->ra = sfi->ra;
259 tmpsfi->xpc = sfi->xpc;
261 /* Set the previous stackframe info of the temporary one to the
262 next in the chain. */
264 tmpsfi->prev = sfi->prev;
267 if (opt_DebugStackTrace)
268 log_println("[stacktrace fill]");
273 /* stacktrace_stackframeinfo_next **********************************************
275 Walk the stack (or the stackframeinfo-chain) to the next method and
276 return the new stackframe values in the temporary stackframeinfo
279 ATTENTION: This function does NOT skip builtin methods!
282 tmpsfi ... temporary stackframeinfo of current method
284 *******************************************************************************/
286 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
294 stackframeinfo_t *prevsfi;
298 assert(tmpsfi != NULL);
300 /* Get values from the stackframeinfo. */
308 /* Get the current stack frame size. */
310 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
312 /* Get the RA of the current stack frame (RA to the parent Java
313 method) if the current method is a non-leaf method. Otherwise
314 the value in the stackframeinfo is correct (from the signal
317 #if defined(ENABLE_JIT)
318 # if defined(ENABLE_INTRP)
320 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
324 if (!code_is_leafmethod(code))
325 ra = md_stacktrace_get_returnaddress(sp, framesize);
328 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
331 /* Get the PV for the parent Java method. */
333 #if defined(ENABLE_INTRP)
335 pv = methodtree_find(ra);
339 #if defined(ENABLE_JIT)
340 # if defined(__SPARC_64__)
341 sp = md_get_framepointer(sp);
342 pv = md_get_pv_from_stackframe(sp);
344 pv = md_codegen_get_pv_from_pc(ra);
349 /* Get the codeinfo pointer for the parent Java method. */
351 code = code_get_codeinfo_for_pv(pv);
353 /* Calculate the SP for the parent Java method. */
355 #if defined(ENABLE_INTRP)
357 sp = *(u1 **) (sp - framesize);
361 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
362 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
363 #elif defined(__SPARC_64__)
364 /* already has the new sp */
366 sp = (void *) (((intptr_t) sp) + framesize);
370 /* If the new codeinfo pointer is NULL we reached a
371 asm_vm_call_method function. In this case we get the next
372 values from the previous stackframeinfo in the chain.
373 Otherwise the new values have been calculated before. */
376 prevsfi = tmpsfi->prev;
378 /* If the previous stackframeinfo in the chain is NULL we
379 reached the top of the stacktrace. We set code and prev to
380 NULL to mark the end, which is checked in
381 stacktrace_stackframeinfo_end_check. */
383 if (prevsfi == NULL) {
389 /* Fill the temporary stackframeinfo with the new values. */
391 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
394 /* Store the new values in the stackframeinfo. NOTE: We
395 subtract 1 from the RA to get the XPC, because the RA
396 points to the instruction after the call instruction. */
402 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
406 /* Print current method information. */
408 if (opt_DebugStackTrace) {
410 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
411 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
413 method_print(tmpsfi->code->m);
421 /* stacktrace_stackframeinfo_end_check *****************************************
423 Check if we reached the end of the stacktrace.
426 tmpsfi ... temporary stackframeinfo of current method
429 true .... the end is reached
430 false ... the end is not reached
432 *******************************************************************************/
434 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
438 assert(tmpsfi != NULL);
440 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
442 if (opt_DebugStackTrace)
443 log_println("[stacktrace stop]");
453 /* stacktrace_depth ************************************************************
455 Calculates and returns the depth of the current stacktrace.
458 sfi ... stackframeinfo where to start the stacktrace
461 depth of the stacktrace
463 *******************************************************************************/
465 static int stacktrace_depth(stackframeinfo_t *sfi)
467 stackframeinfo_t tmpsfi;
472 if (opt_DebugStackTrace)
473 log_println("[stacktrace_depth]");
476 /* XXX This is not correct, but a workaround for threads-dump for
478 /* assert(sfi != NULL); */
482 /* Iterate over all stackframes. */
486 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
487 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
488 stacktrace_stackframeinfo_next(&tmpsfi)) {
489 /* Get methodinfo. */
493 /* Skip builtin methods. */
495 if (m->flags & ACC_METHOD_BUILTIN)
505 /* stacktrace_get **************************************************************
507 Builds and returns a stacktrace starting from the given stackframe
508 info and returns the stacktrace structure wrapped in a Java
509 byte-array to not confuse the GC.
512 sfi ... stackframe info to start stacktrace from
515 stacktrace as Java byte-array
517 *******************************************************************************/
519 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
521 stackframeinfo_t tmpsfi;
523 java_handle_bytearray_t *ba;
526 stacktrace_entry_t *ste;
528 bool skip_fillInStackTrace;
531 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
534 if (opt_DebugStackTrace)
535 log_println("[stacktrace_get]");
538 skip_fillInStackTrace = true;
541 depth = stacktrace_depth(sfi);
546 /* Allocate memory from the GC heap and copy the stacktrace
548 /* ATTENTION: Use a Java byte-array for this to not confuse the
550 /* FIXME: We waste some memory here as we skip some entries
553 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
555 ba = builtin_newarray_byte(ba_size);
560 /* Get a stacktrace entry pointer. */
561 /* ATTENTION: We need a critical section here because we use the
562 byte-array data pointer directly. */
566 st = (stacktrace_t *) LLNI_array_data(ba);
570 /* Iterate over the whole stack. */
572 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
573 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
574 stacktrace_stackframeinfo_next(&tmpsfi)) {
575 /* Get the methodinfo. */
579 /* Skip builtin methods. */
581 if (m->flags & ACC_METHOD_BUILTIN)
584 /* This logic is taken from
585 hotspot/src/share/vm/classfile/javaClasses.cpp
586 (java_lang_Throwable::fill_in_stack_trace). */
588 if (skip_fillInStackTrace == true) {
589 /* Check "fillInStackTrace" only once, so we negate the
590 flag after the first time check. */
592 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
593 /* For GNU Classpath we also need to skip
594 VMThrowable.fillInStackTrace(). */
596 if ((m->clazz == class_java_lang_VMThrowable) &&
597 (m->name == utf_fillInStackTrace))
601 skip_fillInStackTrace = false;
603 if (m->name == utf_fillInStackTrace)
607 /* Skip <init> methods of the exceptions klass. If there is
608 <init> methods that belongs to a superclass of the
609 exception we are going to skipping them in stack trace. */
611 if (skip_init == true) {
612 if ((m->name == utf_init) &&
613 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
617 /* If no "Throwable.init()" method found, we stop
618 checking it next time. */
624 /* Store the stacktrace entry and increment the pointer. */
626 ste->code = tmpsfi.code;
627 ste->pc = tmpsfi.xpc;
632 /* Store the number of entries in the stacktrace structure. */
634 st->length = ste - st->entries;
638 /* release dump memory */
640 /* dump_release(dumpsize); */
642 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
647 /* dump_release(dumpsize); */
649 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
656 /* stacktrace_get_current ******************************************************
658 Builds and returns a stacktrace from the current thread and returns
659 the stacktrace structure wrapped in a Java byte-array to not
663 stacktrace as Java byte-array
665 *******************************************************************************/
667 java_handle_bytearray_t *stacktrace_get_current(void)
669 stackframeinfo_t *sfi;
670 java_handle_bytearray_t *ba;
672 sfi = threads_get_current_stackframeinfo();
673 ba = stacktrace_get(sfi);
679 /* stacktrace_get_caller_class *************************************************
681 Get the class on the stack at the given depth. This function skips
682 various special classes or methods.
685 depth ... depth to get caller class of
690 *******************************************************************************/
692 #if defined(ENABLE_JAVASE)
693 classinfo *stacktrace_get_caller_class(int depth)
695 stackframeinfo_t *sfi;
696 stackframeinfo_t tmpsfi;
702 if (opt_DebugStackTrace)
703 log_println("[stacktrace_get_caller_class]");
706 /* Get the stackframeinfo of the current thread. */
708 sfi = threads_get_current_stackframeinfo();
710 /* Iterate over the whole stack until we reached the requested
715 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
716 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
717 stacktrace_stackframeinfo_next(&tmpsfi)) {
722 /* Skip builtin methods. */
724 if (m->flags & ACC_METHOD_BUILTIN)
727 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
728 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
729 (vframeStreamCommon::security_get_caller_frame). */
731 /* This is java.lang.reflect.Method.invoke(), skip it. */
733 if (m == method_java_lang_reflect_Method_invoke)
736 /* This is an auxiliary frame, skip it. */
738 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
742 /* We reached the requested depth. */
755 /* stacktrace_first_nonnull_classloader ****************************************
757 Returns the first non-null (user-defined) classloader on the stack.
758 If none is found NULL is returned.
763 *******************************************************************************/
765 classloader_t *stacktrace_first_nonnull_classloader(void)
767 stackframeinfo_t *sfi;
768 stackframeinfo_t tmpsfi;
773 if (opt_DebugStackTrace)
774 log_println("[stacktrace_first_nonnull_classloader]");
777 /* Get the stackframeinfo of the current thread. */
779 sfi = threads_get_current_stackframeinfo();
781 /* Iterate over the whole stack. */
783 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
784 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
785 stacktrace_stackframeinfo_next(&tmpsfi)) {
788 cl = class_get_classloader(m->clazz);
798 /* stacktrace_getClassContext **************************************************
800 Creates a Class context array.
803 the array of java.lang.Class objects, or
804 NULL if an exception has been thrown
806 *******************************************************************************/
808 java_handle_objectarray_t *stacktrace_getClassContext(void)
810 stackframeinfo_t *sfi;
811 stackframeinfo_t tmpsfi;
813 java_handle_objectarray_t *oa;
814 java_object_t **data;
818 CYCLES_STATS_DECLARE_AND_START
821 if (opt_DebugStackTrace)
822 log_println("[stacktrace_getClassContext]");
825 sfi = threads_get_current_stackframeinfo();
827 /* Get the depth of the current stack. */
829 depth = stacktrace_depth(sfi);
831 /* The first stackframe corresponds to the method whose
832 implementation calls this native function. We remove that
836 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
837 stacktrace_stackframeinfo_next(&tmpsfi);
839 /* Allocate the Class array. */
841 oa = builtin_anewarray(depth, class_java_lang_Class);
844 CYCLES_STATS_END(stacktrace_getClassContext);
849 /* Fill the Class array from the stacktrace list. */
853 data = LLNI_array_data(oa);
855 /* Iterate over the whole stack. */
860 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
861 stacktrace_stackframeinfo_next(&tmpsfi)) {
862 /* Get methodinfo. */
866 /* Skip builtin methods. */
868 if (m->flags & ACC_METHOD_BUILTIN)
871 /* Store the class in the array. */
873 data[i] = (java_object_t *) m->clazz;
880 CYCLES_STATS_END(stacktrace_getClassContext)
886 /* stacktrace_getCurrentClass **************************************************
888 Find the current class by walking the stack trace.
890 Quote from the JNI documentation:
892 In the Java 2 Platform, FindClass locates the class loader
893 associated with the current native method. If the native code
894 belongs to a system class, no class loader will be
895 involved. Otherwise, the proper class loader will be invoked to
896 load and link the named class. When FindClass is called through the
897 Invocation Interface, there is no current native method or its
898 associated class loader. In that case, the result of
899 ClassLoader.getBaseClassLoader is used."
901 *******************************************************************************/
903 #if defined(ENABLE_JAVASE)
904 classinfo *stacktrace_get_current_class(void)
906 stackframeinfo_t *sfi;
907 stackframeinfo_t tmpsfi;
910 CYCLES_STATS_DECLARE_AND_START;
913 if (opt_DebugStackTrace)
914 log_println("[stacktrace_get_current_class]");
917 /* Get the stackframeinfo of the current thread. */
919 sfi = threads_get_current_stackframeinfo();
921 /* If the stackframeinfo is NULL then FindClass is called through
922 the Invocation Interface and we return NULL */
925 CYCLES_STATS_END(stacktrace_getCurrentClass);
930 /* Iterate over the whole stack. */
932 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
933 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
934 stacktrace_stackframeinfo_next(&tmpsfi)) {
935 /* Get the methodinfo. */
939 if (m->clazz == class_java_security_PrivilegedAction) {
940 CYCLES_STATS_END(stacktrace_getCurrentClass);
945 if (m->clazz != NULL) {
946 CYCLES_STATS_END(stacktrace_getCurrentClass);
952 /* No Java method found on the stack. */
954 CYCLES_STATS_END(stacktrace_getCurrentClass);
958 #endif /* ENABLE_JAVASE */
961 /* stacktrace_get_stack ********************************************************
963 Create a 2-dimensional array for java.security.VMAccessControler.
967 NULL if an exception has been thrown
969 *******************************************************************************/
971 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
972 java_handle_objectarray_t *stacktrace_get_stack(void)
974 stackframeinfo_t *sfi;
975 stackframeinfo_t tmpsfi;
977 java_handle_objectarray_t *oa;
978 java_handle_objectarray_t *classes;
979 java_handle_objectarray_t *methodnames;
981 java_handle_t *string;
984 CYCLES_STATS_DECLARE_AND_START
987 if (opt_DebugStackTrace)
988 log_println("[stacktrace_get_stack]");
991 /* Get the stackframeinfo of the current thread. */
993 sfi = threads_get_current_stackframeinfo();
995 /* Get the depth of the current stack. */
997 depth = stacktrace_depth(sfi);
1002 /* Allocate the required arrays. */
1004 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1009 classes = builtin_anewarray(depth, class_java_lang_Class);
1011 if (classes == NULL)
1014 methodnames = builtin_anewarray(depth, class_java_lang_String);
1016 if (methodnames == NULL)
1019 /* Set up the 2-dimensional array. */
1021 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1022 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1024 /* Iterate over the whole stack. */
1025 /* TODO We should use a critical section here to speed things
1030 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1031 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1032 stacktrace_stackframeinfo_next(&tmpsfi)) {
1033 /* Get the methodinfo. */
1037 /* Skip builtin methods. */
1039 if (m->flags & ACC_METHOD_BUILTIN)
1042 /* Store the class in the array. */
1043 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1046 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1048 /* Store the name in the array. */
1050 string = javastring_new(m->name);
1055 array_objectarray_element_set(methodnames, i, string);
1060 CYCLES_STATS_END(stacktrace_get_stack)
1065 CYCLES_STATS_END(stacktrace_get_stack)
1072 /* stacktrace_print_entry ****************************************************
1074 Print line for a stacktrace entry.
1077 m ............ methodinfo of the entry
1078 linenumber ... linenumber of the entry
1080 *******************************************************************************/
1082 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1090 if (m->flags & ACC_METHOD_BUILTIN)
1093 utf_display_printable_ascii_classname(m->clazz->name);
1096 utf_display_printable_ascii(m->name);
1097 utf_display_printable_ascii(m->descriptor);
1099 if (m->flags & ACC_NATIVE) {
1100 puts("(Native Method)");
1103 if (m->flags & ACC_METHOD_BUILTIN) {
1108 utf_display_printable_ascii(m->clazz->sourcefile);
1109 printf(":%d)\n", linenumber);
1117 /* stacktrace_print ************************************************************
1119 Print the given stacktrace with CACAO intern methods only (no Java
1122 This method is used by stacktrace_dump_trace and
1123 builtin_trace_exception.
1126 st ... stacktrace to print
1128 *******************************************************************************/
1130 void stacktrace_print(stacktrace_t *st)
1132 stacktrace_entry_t *ste;
1137 ste = &(st->entries[0]);
1139 for (i = 0; i < st->length; i++, ste++) {
1142 /* Get the line number. */
1144 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1146 stacktrace_print_entry(m, linenumber);
1151 /* stacktrace_print_current ****************************************************
1153 Print the current stacktrace of the current thread.
1155 NOTE: This function prints all frames of the stacktrace and does
1156 not skip frames like stacktrace_get.
1158 *******************************************************************************/
1160 void stacktrace_print_current(void)
1162 stackframeinfo_t *sfi;
1163 stackframeinfo_t tmpsfi;
1168 sfi = threads_get_current_stackframeinfo();
1171 puts("\t<<No stacktrace available>>");
1176 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1177 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1178 stacktrace_stackframeinfo_next(&tmpsfi)) {
1179 /* Get the methodinfo. */
1184 /* Get the line number. */
1186 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1188 stacktrace_print_entry(m, linenumber);
1193 /* stacktrace_print_of_thread **************************************************
1195 Print the current stacktrace of the given thread.
1200 *******************************************************************************/
1202 #if defined(ENABLE_THREADS)
1203 void stacktrace_print_of_thread(threadobject *t)
1205 stackframeinfo_t *sfi;
1206 stackframeinfo_t tmpsfi;
1211 /* Build a stacktrace for the passed thread. */
1213 sfi = t->_stackframeinfo;
1216 puts("\t<<No stacktrace available>>");
1221 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1222 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1223 stacktrace_stackframeinfo_next(&tmpsfi)) {
1224 /* Get the methodinfo. */
1229 /* Get the line number. */
1231 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1233 stacktrace_print_entry(m, linenumber);
1239 /* stacktrace_print_exception **************************************************
1241 Print the stacktrace of a given exception (more or less a wrapper
1242 to stacktrace_print).
1245 h ... handle of exception to print
1247 *******************************************************************************/
1249 void stacktrace_print_exception(java_handle_t *h)
1254 java_lang_Throwable t(h);
1256 /* now print the stacktrace */
1258 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1260 java_lang_VMThrowable vmt(t.get_vmState());
1261 java_handle_bytearray_t* backtrace = vmt.get_vmdata();
1263 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1265 java_handle_bytearray_t* backtrace = t.get_backtrace();
1268 # error unknown classpath configuration
1273 assert(backtrace != NULL);
1275 /* We need a critical section here as we use the byte-array data
1276 pointer directly. */
1278 LLNI_CRITICAL_START;
1280 stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
1282 stacktrace_print(st);
1288 #if defined(ENABLE_CYCLES_STATS)
1289 void stacktrace_print_cycles_stats(FILE *file)
1291 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1292 CYCLES_STATS_PRINT(stacktrace_get, file);
1293 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1294 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1295 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1303 * These are local overrides for various environment variables in Emacs.
1304 * Please do not remove this and leave it at the end of the file, where
1305 * Emacs will automagically detect them.
1306 * ---------------------------------------------------------------------
1309 * indent-tabs-mode: t
1313 * vim:noexpandtab:sw=4:ts=4: