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_CLASSPATH_GNU)
50 # include "native/include/gnu_classpath_Pointer.h"
51 # include "native/include/java_lang_VMThrowable.h"
54 #if defined(ENABLE_THREADS)
55 # include "threads/native/threads.h"
57 # include "threads/none/threads.h"
60 #include "toolbox/logging.h"
63 #include "vm/builtin.h"
64 #include "vm/cycles-stats.h"
65 #include "vm/exceptions.h"
66 #include "vm/stringlocal.h"
69 #include "vm/jit/asmpart.h"
70 #include "vm/jit/codegen-common.h"
71 #include "vm/jit/linenumbertable.h"
72 #include "vm/jit/methodheader.h"
73 #include "vm/jit/methodtree.h"
75 #include "vmcore/class.h"
76 #include "vmcore/loader.h"
77 #include "vmcore/method.h"
78 #include "vmcore/options.h"
81 /* global variables ***********************************************************/
83 #if !defined(ENABLE_THREADS)
84 stackframeinfo_t *_no_threads_stackframeinfo = NULL;
87 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
88 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
89 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
90 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
91 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
94 /* stacktrace_stackframeinfo_add ***********************************************
96 Fills a stackframe info structure with the given or calculated
97 values and adds it to the chain.
99 *******************************************************************************/
101 void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
103 stackframeinfo_t *currentsfi;
105 #if defined(ENABLE_JIT)
109 /* Get current stackframe info. */
111 currentsfi = threads_get_current_stackframeinfo();
113 /* sometimes we don't have pv handy (e.g. in asmpart.S:
114 L_asm_call_jit_compiler_exception or in the interpreter). */
117 #if defined(ENABLE_INTRP)
119 pv = methodtree_find(ra);
123 #if defined(ENABLE_JIT)
124 # if defined(__SPARC_64__)
125 pv = md_get_pv_from_stackframe(sp);
127 pv = md_codegen_get_pv_from_pc(ra);
133 /* Get codeinfo pointer for the parent Java method. */
135 code = code_get_codeinfo_for_pv(pv);
138 /* assert(m != NULL); */
140 #if defined(ENABLE_JIT)
141 # if defined(ENABLE_INTRP)
142 /* When using the interpreter, we pass RA to the function. */
146 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
147 /* On i386 and x86_64 we always have to get the return address
149 /* m68k has return address on stack always */
150 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
151 the RA from stack. */
153 framesize = *((u4 *) (pv + FrameSize));
155 ra = md_stacktrace_get_returnaddress(sp, framesize);
157 /* If the method is a non-leaf function, we need to get the
158 return address from the stack. For leaf functions the
159 return address is set correctly. This makes the assembler
160 and the signal handler code simpler. The code is NULL is
161 the asm_vm_call_method special case. */
163 if ((code == NULL) || !code_is_leafmethod(code)) {
164 framesize = *((u4 *) (pv + FrameSize));
166 ra = md_stacktrace_get_returnaddress(sp, framesize);
169 # if defined(ENABLE_INTRP)
174 /* Calculate XPC when not given. The XPC is then the return
175 address of the current method minus 1 because the RA points to
176 the instruction after the call instruction. This is required
177 e.g. for method stubs. */
180 xpc = (void *) (((intptr_t) ra) - 1);
183 /* Fill new stackframeinfo structure. */
185 sfi->prev = currentsfi;
193 if (opt_DebugStackFrameInfo) {
195 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
196 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
197 method_print(sfi->code->m);
203 /* Store new stackframeinfo pointer. */
205 threads_set_current_stackframeinfo(sfi);
207 /* set the native world flag for the current thread */
208 /* ATTENTION: This flag tells the GC how to treat this thread in case of
209 a collection. Set this flag _after_ a valid stackframe info was set. */
211 THREAD_NATIVEWORLD_ENTER;
215 /* stacktrace_stackframeinfo_remove ********************************************
217 Remove the given stackframeinfo from the chain in the current
220 *******************************************************************************/
222 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
224 /* Clear the native world flag for the current thread. */
225 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
227 THREAD_NATIVEWORLD_EXIT;
230 if (opt_DebugStackFrameInfo) {
232 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
233 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
234 method_print(sfi->code->m);
240 /* Set previous stackframe info. */
242 threads_set_current_stackframeinfo(sfi->prev);
246 /* stacktrace_stackframeinfo_fill **********************************************
248 Fill the temporary stackframeinfo structure with the values given
252 tmpsfi ... temporary stackframeinfo
253 sfi ...... stackframeinfo to be used in the next iteration
255 *******************************************************************************/
257 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
261 assert(tmpsfi != NULL);
264 /* Fill the temporary stackframeinfo. */
266 tmpsfi->code = sfi->code;
267 tmpsfi->pv = sfi->pv;
268 tmpsfi->sp = sfi->sp;
269 tmpsfi->ra = sfi->ra;
270 tmpsfi->xpc = sfi->xpc;
272 /* Set the previous stackframe info of the temporary one to the
273 next in the chain. */
275 tmpsfi->prev = sfi->prev;
278 /* Print current method information. */
280 if (opt_DebugStackTrace) {
281 log_println("[stacktrace start]");
283 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
284 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
286 method_print(tmpsfi->code->m);
294 /* stacktrace_stackframeinfo_next **********************************************
296 Walk the stack (or the stackframeinfo-chain) to the next method and
297 return the new stackframe values in the temporary stackframeinfo
300 ATTENTION: This function does NOT skip builtin methods!
303 tmpsfi ... temporary stackframeinfo of current method
305 *******************************************************************************/
307 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
315 stackframeinfo_t *prevsfi;
319 assert(tmpsfi != NULL);
321 /* Get values from the stackframeinfo. */
329 /* Get the current stack frame size. */
331 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
333 /* Get the RA of the current stack frame (RA to the parent Java
334 method) if the current method is a non-leaf method. Otherwise
335 the value in the stackframeinfo is correct (from the signal
338 #if defined(ENABLE_JIT)
339 # if defined(ENABLE_INTRP)
341 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
345 if (!code_is_leafmethod(code))
346 ra = md_stacktrace_get_returnaddress(sp, framesize);
349 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
352 /* Get the PV for the parent Java method. */
354 #if defined(ENABLE_INTRP)
356 pv = methodtree_find(ra);
360 #if defined(ENABLE_JIT)
361 # if defined(__SPARC_64__)
362 sp = md_get_framepointer(sp);
363 pv = md_get_pv_from_stackframe(sp);
365 pv = md_codegen_get_pv_from_pc(ra);
370 /* Get the codeinfo pointer for the parent Java method. */
372 code = code_get_codeinfo_for_pv(pv);
374 /* Calculate the SP for the parent Java method. */
376 #if defined(ENABLE_INTRP)
378 sp = *(u1 **) (sp - framesize);
382 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
383 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
384 #elif defined(__SPARC_64__)
385 /* already has the new sp */
387 sp = (void *) (((intptr_t) sp) + framesize);
391 /* If the new codeinfo pointer is NULL we reached a
392 asm_vm_call_method function. In this case we get the next
393 values from the previous stackframeinfo in the chain.
394 Otherwise the new values have been calculated before. */
397 prevsfi = tmpsfi->prev;
399 /* If the previous stackframeinfo in the chain is NULL we
400 reached the top of the stacktrace. We set code and prev to
401 NULL to mark the end, which is checked in
402 stacktrace_stackframeinfo_end_check. */
404 if (prevsfi == NULL) {
410 /* Fill the temporary stackframeinfo with the new values. */
412 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
415 /* Store the new values in the stackframeinfo. NOTE: We
416 subtract 1 from the RA to get the XPC, because the RA
417 points to the instruction after the call instruction. */
423 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
427 /* Print current method information. */
429 if (opt_DebugStackTrace) {
431 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
432 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
434 method_print(tmpsfi->code->m);
442 /* stacktrace_stackframeinfo_end_check *****************************************
444 Check if we reached the end of the stacktrace.
447 tmpsfi ... temporary stackframeinfo of current method
450 true .... the end is reached
451 false ... the end is not reached
453 *******************************************************************************/
455 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
459 assert(tmpsfi != NULL);
461 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
463 if (opt_DebugStackTrace)
464 log_println("[stacktrace stop]");
474 /* stacktrace_depth ************************************************************
476 Calculates and returns the depth of the current stacktrace.
479 sfi ... stackframeinfo where to start the stacktrace
482 depth of the stacktrace
484 *******************************************************************************/
486 static int stacktrace_depth(stackframeinfo_t *sfi)
488 stackframeinfo_t tmpsfi;
493 if (opt_DebugStackTrace)
494 log_println("[stacktrace_depth]");
497 /* XXX This is not correct, but a workaround for threads-dump for
499 /* assert(sfi != NULL); */
503 /* Iterate over all stackframes. */
507 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
508 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
509 stacktrace_stackframeinfo_next(&tmpsfi)) {
510 /* Get methodinfo. */
514 /* Skip builtin methods. */
516 if (m->flags & ACC_METHOD_BUILTIN)
526 /* stacktrace_get **************************************************************
528 Builds and returns a stacktrace starting from the given stackframe
529 info and returns the stacktrace structure wrapped in a Java
530 byte-array to not confuse the GC.
533 sfi ... stackframe info to start stacktrace from
536 stacktrace as Java byte-array
538 *******************************************************************************/
540 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
542 stackframeinfo_t tmpsfi;
544 java_handle_bytearray_t *ba;
547 stacktrace_entry_t *ste;
549 bool skip_fillInStackTrace;
552 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
555 if (opt_DebugStackTrace)
556 log_println("[stacktrace_get]");
559 skip_fillInStackTrace = true;
562 depth = stacktrace_depth(sfi);
567 /* Allocate memory from the GC heap and copy the stacktrace
569 /* ATTENTION: Use a Java byte-array for this to not confuse the
571 /* FIXME: We waste some memory here as we skip some entries
574 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
576 ba = builtin_newarray_byte(ba_size);
581 /* Get a stacktrace entry pointer. */
582 /* ATTENTION: We need a critical section here because we use the
583 byte-array data pointer directly. */
587 st = (stacktrace_t *) LLNI_array_data(ba);
591 /* Iterate over the whole stack. */
593 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
594 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
595 stacktrace_stackframeinfo_next(&tmpsfi)) {
596 /* Get the methodinfo. */
600 /* Skip builtin methods. */
602 if (m->flags & ACC_METHOD_BUILTIN)
605 /* This logic is taken from
606 hotspot/src/share/vm/classfile/javaClasses.cpp
607 (java_lang_Throwable::fill_in_stack_trace). */
609 if (skip_fillInStackTrace == true) {
610 /* Check "fillInStackTrace" only once, so we negate the
611 flag after the first time check. */
613 #if defined(WITH_CLASSPATH_GNU)
614 /* For GNU Classpath we also need to skip
615 VMThrowable.fillInStackTrace(). */
617 if ((m->class == class_java_lang_VMThrowable) &&
618 (m->name == utf_fillInStackTrace))
622 skip_fillInStackTrace = false;
624 if (m->name == utf_fillInStackTrace)
628 /* Skip <init> methods of the exceptions klass. If there is
629 <init> methods that belongs to a superclass of the
630 exception we are going to skipping them in stack trace. */
632 if (skip_init == true) {
633 if (m->name == utf_init) {
634 /* throwable->is_a(method->method_holder())) { */
638 /* If no "Throwable.init()" method found, we stop
639 checking it next time. */
645 /* Store the stacktrace entry and increment the pointer. */
647 ste->code = tmpsfi.code;
648 ste->pc = tmpsfi.xpc;
653 /* Store the number of entries in the stacktrace structure. */
655 st->length = ste - st->entries;
659 /* release dump memory */
661 /* dump_release(dumpsize); */
663 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
668 /* dump_release(dumpsize); */
670 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
677 /* stacktrace_get_current ******************************************************
679 Builds and returns a stacktrace from the current thread and returns
680 the stacktrace structure wrapped in a Java byte-array to not
684 stacktrace as Java byte-array
686 *******************************************************************************/
688 java_handle_bytearray_t *stacktrace_get_current(void)
690 stackframeinfo_t *sfi;
691 java_handle_bytearray_t *ba;
693 sfi = threads_get_current_stackframeinfo();
694 ba = stacktrace_get(sfi);
700 /* stacktrace_get_caller_class *************************************************
702 Get the class on the stack at the given depth. This function skips
703 various special classes or methods.
706 depth ... depth to get caller class of
711 *******************************************************************************/
713 #if defined(ENABLE_JAVASE)
714 classinfo *stacktrace_get_caller_class(int depth)
716 stackframeinfo_t *sfi;
717 stackframeinfo_t tmpsfi;
723 if (opt_DebugStackTrace)
724 log_println("[stacktrace_get_caller_class]");
727 /* Get the stackframeinfo of the current thread. */
729 sfi = threads_get_current_stackframeinfo();
731 /* Iterate over the whole stack until we reached the requested
736 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
737 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
738 stacktrace_stackframeinfo_next(&tmpsfi)) {
743 /* Skip builtin methods. */
745 if (m->flags & ACC_METHOD_BUILTIN)
748 #if defined(WITH_CLASSPATH_SUN)
749 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
750 (vframeStreamCommon::security_get_caller_frame). */
752 /* This is java.lang.reflect.Method.invoke(), skip it. */
754 if (m == method_java_lang_reflect_Method_invoke)
757 /* This is an auxiliary frame, skip it. */
759 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
763 /* We reached the requested depth. */
776 /* stacktrace_first_nonnull_classloader ****************************************
778 Returns the first non-null (user-defined) classloader on the stack.
779 If none is found NULL is returned.
784 *******************************************************************************/
786 classloader *stacktrace_first_nonnull_classloader(void)
788 stackframeinfo_t *sfi;
789 stackframeinfo_t tmpsfi;
794 if (opt_DebugStackTrace)
795 log_println("[stacktrace_first_nonnull_classloader]");
798 /* Get the stackframeinfo of the current thread. */
800 sfi = threads_get_current_stackframeinfo();
802 /* Iterate over the whole stack. */
804 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
805 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
806 stacktrace_stackframeinfo_next(&tmpsfi)) {
809 cl = class_get_classloader(m->class);
819 /* stacktrace_getClassContext **************************************************
821 Creates a Class context array.
824 the array of java.lang.Class objects, or
825 NULL if an exception has been thrown
827 *******************************************************************************/
829 java_handle_objectarray_t *stacktrace_getClassContext(void)
831 stackframeinfo_t *sfi;
832 stackframeinfo_t tmpsfi;
834 java_handle_objectarray_t *oa;
835 java_object_t **data;
839 CYCLES_STATS_DECLARE_AND_START
842 if (opt_DebugStackTrace)
843 log_println("[stacktrace_getClassContext]");
846 sfi = threads_get_current_stackframeinfo();
848 /* Get the depth of the current stack. */
850 depth = stacktrace_depth(sfi);
852 /* The first stackframe corresponds to the method whose
853 implementation calls this native function. We remove that
857 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
858 stacktrace_stackframeinfo_next(&tmpsfi);
860 /* Allocate the Class array. */
862 oa = builtin_anewarray(depth, class_java_lang_Class);
865 CYCLES_STATS_END(stacktrace_getClassContext);
870 /* Fill the Class array from the stacktrace list. */
874 data = LLNI_array_data(oa);
876 /* Iterate over the whole stack. */
881 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
882 stacktrace_stackframeinfo_next(&tmpsfi)) {
883 /* Get methodinfo. */
887 /* Skip builtin methods. */
889 if (m->flags & ACC_METHOD_BUILTIN)
892 /* Store the class in the array. */
894 data[i] = (java_object_t *) m->class;
901 CYCLES_STATS_END(stacktrace_getClassContext)
907 /* stacktrace_getCurrentClass **************************************************
909 Find the current class by walking the stack trace.
911 Quote from the JNI documentation:
913 In the Java 2 Platform, FindClass locates the class loader
914 associated with the current native method. If the native code
915 belongs to a system class, no class loader will be
916 involved. Otherwise, the proper class loader will be invoked to
917 load and link the named class. When FindClass is called through the
918 Invocation Interface, there is no current native method or its
919 associated class loader. In that case, the result of
920 ClassLoader.getBaseClassLoader is used."
922 *******************************************************************************/
924 #if defined(ENABLE_JAVASE)
925 classinfo *stacktrace_get_current_class(void)
927 stackframeinfo_t *sfi;
928 stackframeinfo_t tmpsfi;
931 CYCLES_STATS_DECLARE_AND_START;
934 if (opt_DebugStackTrace)
935 log_println("[stacktrace_get_current_class]");
938 /* Get the stackframeinfo of the current thread. */
940 sfi = threads_get_current_stackframeinfo();
942 /* If the stackframeinfo is NULL then FindClass is called through
943 the Invocation Interface and we return NULL */
946 CYCLES_STATS_END(stacktrace_getCurrentClass);
951 /* Iterate over the whole stack. */
953 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
954 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
955 stacktrace_stackframeinfo_next(&tmpsfi)) {
956 /* Get the methodinfo. */
960 if (m->class == class_java_security_PrivilegedAction) {
961 CYCLES_STATS_END(stacktrace_getCurrentClass);
966 if (m->class != NULL) {
967 CYCLES_STATS_END(stacktrace_getCurrentClass);
973 /* No Java method found on the stack. */
975 CYCLES_STATS_END(stacktrace_getCurrentClass);
979 #endif /* ENABLE_JAVASE */
982 /* stacktrace_get_stack ********************************************************
984 Create a 2-dimensional array for java.security.VMAccessControler.
988 NULL if an exception has been thrown
990 *******************************************************************************/
992 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
993 java_handle_objectarray_t *stacktrace_get_stack(void)
995 stackframeinfo_t *sfi;
996 stackframeinfo_t tmpsfi;
998 java_handle_objectarray_t *oa;
999 java_handle_objectarray_t *classes;
1000 java_handle_objectarray_t *methodnames;
1002 java_handle_t *string;
1005 CYCLES_STATS_DECLARE_AND_START
1007 #if !defined(NDEBUG)
1008 if (opt_DebugStackTrace)
1009 log_println("[stacktrace_get_stack]");
1012 /* Get the stackframeinfo of the current thread. */
1014 sfi = threads_get_current_stackframeinfo();
1016 /* Get the depth of the current stack. */
1018 depth = stacktrace_depth(sfi);
1023 /* Allocate the required arrays. */
1025 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1030 classes = builtin_anewarray(depth, class_java_lang_Class);
1032 if (classes == NULL)
1035 methodnames = builtin_anewarray(depth, class_java_lang_String);
1037 if (methodnames == NULL)
1040 /* Set up the 2-dimensional array. */
1042 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1043 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1045 /* Iterate over the whole stack. */
1046 /* TODO We should use a critical section here to speed things
1051 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1052 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1053 stacktrace_stackframeinfo_next(&tmpsfi)) {
1054 /* Get the methodinfo. */
1058 /* Skip builtin methods. */
1060 if (m->flags & ACC_METHOD_BUILTIN)
1063 /* Store the class in the array. */
1064 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1067 LLNI_array_direct(classes, i) = (java_object_t *) m->class;
1069 /* Store the name in the array. */
1071 string = javastring_new(m->name);
1076 array_objectarray_element_set(methodnames, i, string);
1081 CYCLES_STATS_END(stacktrace_get_stack)
1086 CYCLES_STATS_END(stacktrace_get_stack)
1093 /* stacktrace_print ************************************************************
1095 Print the given stacktrace with CACAO intern methods only (no Java
1098 This method is used by stacktrace_dump_trace and
1099 builtin_trace_exception.
1102 st ... stacktrace to print
1104 *******************************************************************************/
1106 void stacktrace_print(stacktrace_t *st)
1108 stacktrace_entry_t *ste;
1113 ste = &(st->entries[0]);
1115 for (i = 0; i < st->length; i++, ste++) {
1118 /* Get the line number. */
1120 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1123 utf_display_printable_ascii_classname(m->class->name);
1125 utf_display_printable_ascii(m->name);
1126 utf_display_printable_ascii(m->descriptor);
1128 if (m->flags & ACC_NATIVE) {
1129 puts("(Native Method)");
1133 utf_display_printable_ascii(m->class->sourcefile);
1134 printf(":%d)\n", linenumber);
1138 /* just to be sure */
1144 /* stacktrace_print_exception **************************************************
1146 Print the stacktrace of a given exception (more or less a wrapper
1147 to stacktrace_print).
1150 h ... handle of exception to print
1152 *******************************************************************************/
1154 void stacktrace_print_exception(java_handle_t *h)
1156 java_lang_Throwable *o;
1158 #if defined(WITH_CLASSPATH_GNU)
1159 java_lang_VMThrowable *vmt;
1162 java_lang_Object *backtrace;
1163 java_handle_bytearray_t *ba;
1166 o = (java_lang_Throwable *) h;
1171 /* now print the stacktrace */
1173 #if defined(WITH_CLASSPATH_GNU)
1175 LLNI_field_get_ref(o, vmState, vmt);
1176 LLNI_field_get_ref(vmt, vmdata, backtrace);
1178 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1180 LLNI_field_get_ref(o, backtrace, backtrace);
1183 # error unknown classpath configuration
1186 ba = (java_handle_bytearray_t *) backtrace;
1192 /* We need a critical section here as we use the byte-array data
1193 pointer directly. */
1195 LLNI_CRITICAL_START;
1197 st = (stacktrace_t *) LLNI_array_data(ba);
1199 stacktrace_print(st);
1205 #if defined(ENABLE_CYCLES_STATS)
1206 void stacktrace_print_cycles_stats(FILE *file)
1208 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1209 CYCLES_STATS_PRINT(stacktrace_get, file);
1210 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1211 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1212 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1218 * These are local overrides for various environment variables in Emacs.
1219 * Please do not remove this and leave it at the end of the file, where
1220 * Emacs will automagically detect them.
1221 * ---------------------------------------------------------------------
1224 * indent-tabs-mode: t
1228 * vim:noexpandtab:sw=4:ts=4: