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"
74 #include "vmcore/class.h"
75 #include "vmcore/loader.h"
76 #include "vmcore/options.h"
79 /* global variables ***********************************************************/
80 #if !defined(ENABLE_THREADS)
81 stackframeinfo_t *_no_threads_stackframeinfo = NULL;
84 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
85 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
86 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
87 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
88 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
91 /* stacktrace_stackframeinfo_add ***********************************************
93 Fills a stackframe info structure with the given or calculated
94 values and adds it to the chain.
96 *******************************************************************************/
98 void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
100 stackframeinfo_t *currentsfi;
102 #if defined(ENABLE_JIT)
106 /* Get current stackframe info. */
108 currentsfi = threads_get_current_stackframeinfo();
110 /* sometimes we don't have pv handy (e.g. in asmpart.S:
111 L_asm_call_jit_compiler_exception or in the interpreter). */
114 #if defined(ENABLE_INTRP)
116 pv = codegen_get_pv_from_pc(ra);
120 #if defined(ENABLE_JIT)
121 # if defined(__SPARC_64__)
122 pv = md_get_pv_from_stackframe(sp);
124 pv = md_codegen_get_pv_from_pc(ra);
130 /* Get codeinfo pointer for the parent Java method. */
132 code = code_get_codeinfo_for_pv(pv);
135 /* assert(m != NULL); */
137 #if defined(ENABLE_JIT)
138 # if defined(ENABLE_INTRP)
139 /* When using the interpreter, we pass RA to the function. */
143 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
144 /* On i386 and x86_64 we always have to get the return address
146 /* m68k has return address on stack always */
147 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
148 the RA from stack. */
150 framesize = *((u4 *) (pv + FrameSize));
152 ra = md_stacktrace_get_returnaddress(sp, framesize);
154 /* If the method is a non-leaf function, we need to get the
155 return address from the stack. For leaf functions the
156 return address is set correctly. This makes the assembler
157 and the signal handler code simpler. The code is NULL is
158 the asm_vm_call_method special case. */
160 if ((code == NULL) || !code_is_leafmethod(code)) {
161 framesize = *((u4 *) (pv + FrameSize));
163 ra = md_stacktrace_get_returnaddress(sp, framesize);
166 # if defined(ENABLE_INTRP)
171 /* Calculate XPC when not given. The XPC is then the return
172 address of the current method minus 1 because the RA points to
173 the instruction after the call instruction. This is required
174 e.g. for method stubs. */
177 xpc = (void *) (((intptr_t) ra) - 1);
180 /* Fill new stackframeinfo structure. */
182 sfi->prev = currentsfi;
190 if (opt_DebugStackFrameInfo) {
192 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
193 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
194 method_print(sfi->code->m);
200 /* Store new stackframeinfo pointer. */
202 threads_set_current_stackframeinfo(sfi);
204 /* set the native world flag for the current thread */
205 /* ATTENTION: This flag tells the GC how to treat this thread in case of
206 a collection. Set this flag _after_ a valid stackframe info was set. */
208 THREAD_NATIVEWORLD_ENTER;
212 /* stacktrace_stackframeinfo_remove ********************************************
214 Remove the given stackframeinfo from the chain in the current
217 *******************************************************************************/
219 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
221 /* Clear the native world flag for the current thread. */
222 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
224 THREAD_NATIVEWORLD_EXIT;
227 if (opt_DebugStackFrameInfo) {
229 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
230 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
231 method_print(sfi->code->m);
237 /* Set previous stackframe info. */
239 threads_set_current_stackframeinfo(sfi->prev);
243 /* stacktrace_stackframeinfo_fill **********************************************
245 Fill the temporary stackframeinfo structure with the values given
249 tmpsfi ... temporary stackframeinfo
250 sfi ...... stackframeinfo to be used in the next iteration
252 *******************************************************************************/
254 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
258 assert(tmpsfi != NULL);
261 /* Fill the temporary stackframeinfo. */
263 tmpsfi->code = sfi->code;
264 tmpsfi->pv = sfi->pv;
265 tmpsfi->sp = sfi->sp;
266 tmpsfi->ra = sfi->ra;
267 tmpsfi->xpc = sfi->xpc;
269 /* Set the previous stackframe info of the temporary one to the
270 next in the chain. */
272 tmpsfi->prev = sfi->prev;
275 /* Print current method information. */
277 if (opt_DebugStackTrace) {
278 log_println("[stacktrace start]");
280 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
281 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
283 method_print(tmpsfi->code->m);
291 /* stacktrace_stackframeinfo_next **********************************************
293 Walk the stack (or the stackframeinfo-chain) to the next method and
294 return the new stackframe values in the temporary stackframeinfo
297 ATTENTION: This function does NOT skip builtin methods!
300 tmpsfi ... temporary stackframeinfo of current method
302 *******************************************************************************/
304 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
312 stackframeinfo_t *prevsfi;
316 assert(tmpsfi != NULL);
318 /* Get values from the stackframeinfo. */
326 /* Get the current stack frame size. */
328 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
330 /* Get the RA of the current stack frame (RA to the parent Java
331 method) if the current method is a non-leaf method. Otherwise
332 the value in the stackframeinfo is correct (from the signal
335 #if defined(ENABLE_JIT)
336 # if defined(ENABLE_INTRP)
338 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
342 if (!code_is_leafmethod(code))
343 ra = md_stacktrace_get_returnaddress(sp, framesize);
346 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
349 /* Get the PV for the parent Java method. */
351 #if defined(ENABLE_INTRP)
353 pv = codegen_get_pv_from_pc(ra);
357 #if defined(ENABLE_JIT)
358 # if defined(__SPARC_64__)
359 sp = md_get_framepointer(sp);
360 pv = md_get_pv_from_stackframe(sp);
362 pv = md_codegen_get_pv_from_pc(ra);
367 /* Get the codeinfo pointer for the parent Java method. */
369 code = code_get_codeinfo_for_pv(pv);
371 /* Calculate the SP for the parent Java method. */
373 #if defined(ENABLE_INTRP)
375 sp = *(u1 **) (sp - framesize);
379 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
380 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
381 #elif defined(__SPARC_64__)
382 /* already has the new sp */
384 sp = (void *) (((intptr_t) sp) + framesize);
388 /* If the new codeinfo pointer is NULL we reached a
389 asm_vm_call_method function. In this case we get the next
390 values from the previous stackframeinfo in the chain.
391 Otherwise the new values have been calculated before. */
394 prevsfi = tmpsfi->prev;
396 /* If the previous stackframeinfo in the chain is NULL we
397 reached the top of the stacktrace. We set code and prev to
398 NULL to mark the end, which is checked in
399 stacktrace_stackframeinfo_end_check. */
401 if (prevsfi == NULL) {
407 /* Fill the temporary stackframeinfo with the new values. */
409 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
412 /* Store the new values in the stackframeinfo. NOTE: We
413 subtract 1 from the RA to get the XPC, because the RA
414 points to the instruction after the call instruction. */
420 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
424 /* Print current method information. */
426 if (opt_DebugStackTrace) {
428 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
429 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
431 method_print(tmpsfi->code->m);
439 /* stacktrace_stackframeinfo_end_check *****************************************
441 Check if we reached the end of the stacktrace.
444 tmpsfi ... temporary stackframeinfo of current method
447 true .... the end is reached
448 false ... the end is not reached
450 *******************************************************************************/
452 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
456 assert(tmpsfi != NULL);
458 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
460 if (opt_DebugStackTrace)
461 log_println("[stacktrace stop]");
471 /* stacktrace_depth ************************************************************
473 Calculates and returns the depth of the current stacktrace.
476 sfi ... stackframeinfo where to start the stacktrace
479 depth of the stacktrace
481 *******************************************************************************/
483 static int stacktrace_depth(stackframeinfo_t *sfi)
485 stackframeinfo_t tmpsfi;
490 if (opt_DebugStackTrace)
491 log_println("[stacktrace_depth]");
494 /* XXX This is not correct, but a workaround for threads-dump for
496 /* assert(sfi != NULL); */
500 /* Iterate over all stackframes. */
504 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
505 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
506 stacktrace_stackframeinfo_next(&tmpsfi)) {
507 /* Get methodinfo. */
511 /* Skip builtin methods. */
513 if (m->flags & ACC_METHOD_BUILTIN)
523 /* stacktrace_get **************************************************************
525 Builds and returns a stacktrace starting from the given stackframe
526 info and returns the stacktrace structure wrapped in a Java
527 byte-array to not confuse the GC.
530 sfi ... stackframe info to start stacktrace from
533 stacktrace as Java byte-array
535 *******************************************************************************/
537 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
539 stackframeinfo_t tmpsfi;
541 java_handle_bytearray_t *ba;
544 stacktrace_entry_t *ste;
546 bool skip_fillInStackTrace;
549 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
552 if (opt_DebugStackTrace)
553 log_println("[stacktrace_get]");
556 skip_fillInStackTrace = true;
559 depth = stacktrace_depth(sfi);
564 /* Allocate memory from the GC heap and copy the stacktrace
566 /* ATTENTION: Use a Java byte-array for this to not confuse the
568 /* FIXME: We waste some memory here as we skip some entries
571 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
573 ba = builtin_newarray_byte(ba_size);
578 /* Get a stacktrace entry pointer. */
579 /* ATTENTION: We need a critical section here because we use the
580 byte-array data pointer directly. */
584 st = (stacktrace_t *) LLNI_array_data(ba);
588 /* Iterate over the whole stack. */
590 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
591 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
592 stacktrace_stackframeinfo_next(&tmpsfi)) {
593 /* Get the methodinfo. */
597 /* Skip builtin methods. */
599 if (m->flags & ACC_METHOD_BUILTIN)
602 /* This logic is taken from
603 hotspot/src/share/vm/classfile/javaClasses.cpp
604 (java_lang_Throwable::fill_in_stack_trace). */
606 if (skip_fillInStackTrace == true) {
607 /* Check "fillInStackTrace" only once, so we negate the
608 flag after the first time check. */
610 #if defined(WITH_CLASSPATH_GNU)
611 /* For GNU Classpath we also need to skip
612 VMThrowable.fillInStackTrace(). */
614 if ((m->class == class_java_lang_VMThrowable) &&
615 (m->name == utf_fillInStackTrace))
619 skip_fillInStackTrace = false;
621 if (m->name == utf_fillInStackTrace)
625 /* Skip <init> methods of the exceptions klass. If there is
626 <init> methods that belongs to a superclass of the
627 exception we are going to skipping them in stack trace. */
629 if (skip_init == true) {
630 if (m->name == utf_init) {
631 /* throwable->is_a(method->method_holder())) { */
635 /* If no "Throwable.init()" method found, we stop
636 checking it next time. */
642 /* Store the stacktrace entry and increment the pointer. */
644 ste->code = tmpsfi.code;
645 ste->pc = tmpsfi.xpc;
650 /* Store the number of entries in the stacktrace structure. */
652 st->length = ste - st->entries;
656 /* release dump memory */
658 /* dump_release(dumpsize); */
660 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
665 /* dump_release(dumpsize); */
667 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
674 /* stacktrace_get_current ******************************************************
676 Builds and returns a stacktrace from the current thread and returns
677 the stacktrace structure wrapped in a Java byte-array to not
681 stacktrace as Java byte-array
683 *******************************************************************************/
685 java_handle_bytearray_t *stacktrace_get_current(void)
687 stackframeinfo_t *sfi;
688 java_handle_bytearray_t *ba;
690 sfi = threads_get_current_stackframeinfo();
691 ba = stacktrace_get(sfi);
697 /* stacktrace_first_nonnull_classloader ****************************************
699 Returns the first non-null (user-defined) classloader on the stack.
700 If none is found NULL is returned.
705 *******************************************************************************/
707 classloader *stacktrace_first_nonnull_classloader(void)
709 stackframeinfo_t *sfi;
710 stackframeinfo_t tmpsfi;
715 if (opt_DebugStackTrace)
716 log_println("[stacktrace_first_nonnull_classloader]");
719 /* Get the stackframeinfo of the current thread. */
721 sfi = threads_get_current_stackframeinfo();
723 /* Iterate over the whole stack. */
725 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
726 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
727 stacktrace_stackframeinfo_next(&tmpsfi)) {
730 cl = class_get_classloader(m->class);
740 /* stacktrace_getClassContext **************************************************
742 Creates a Class context array.
745 the array of java.lang.Class objects, or
746 NULL if an exception has been thrown
748 *******************************************************************************/
750 java_handle_objectarray_t *stacktrace_getClassContext(void)
752 stackframeinfo_t *sfi;
753 stackframeinfo_t tmpsfi;
755 java_handle_objectarray_t *oa;
756 java_object_t **data;
760 CYCLES_STATS_DECLARE_AND_START
763 if (opt_DebugStackTrace)
764 log_println("[stacktrace_getClassContext]");
767 sfi = threads_get_current_stackframeinfo();
769 /* Get the depth of the current stack. */
771 depth = stacktrace_depth(sfi);
773 /* The first stackframe corresponds to the method whose
774 implementation calls this native function. We remove that
778 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
779 stacktrace_stackframeinfo_next(&tmpsfi);
781 /* Allocate the Class array. */
783 oa = builtin_anewarray(depth, class_java_lang_Class);
786 CYCLES_STATS_END(stacktrace_getClassContext);
791 /* Fill the Class array from the stacktrace list. */
795 data = LLNI_array_data(oa);
797 /* Iterate over the whole stack. */
802 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
803 stacktrace_stackframeinfo_next(&tmpsfi)) {
804 /* Get methodinfo. */
808 /* Skip builtin methods. */
810 if (m->flags & ACC_METHOD_BUILTIN)
813 /* Store the class in the array. */
815 data[i] = (java_object_t *) m->class;
822 CYCLES_STATS_END(stacktrace_getClassContext)
828 /* stacktrace_getCurrentClass **************************************************
830 Find the current class by walking the stack trace.
832 Quote from the JNI documentation:
834 In the Java 2 Platform, FindClass locates the class loader
835 associated with the current native method. If the native code
836 belongs to a system class, no class loader will be
837 involved. Otherwise, the proper class loader will be invoked to
838 load and link the named class. When FindClass is called through the
839 Invocation Interface, there is no current native method or its
840 associated class loader. In that case, the result of
841 ClassLoader.getBaseClassLoader is used."
843 *******************************************************************************/
845 #if defined(ENABLE_JAVASE)
846 classinfo *stacktrace_get_current_class(void)
848 stackframeinfo_t *sfi;
849 stackframeinfo_t tmpsfi;
852 CYCLES_STATS_DECLARE_AND_START;
855 if (opt_DebugStackTrace)
856 log_println("[stacktrace_get_current_class]");
859 /* Get the stackframeinfo of the current thread. */
861 sfi = threads_get_current_stackframeinfo();
863 /* If the stackframeinfo is NULL then FindClass is called through
864 the Invocation Interface and we return NULL */
867 CYCLES_STATS_END(stacktrace_getCurrentClass);
872 /* Iterate over the whole stack. */
874 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
875 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
876 stacktrace_stackframeinfo_next(&tmpsfi)) {
877 /* Get the methodinfo. */
881 if (m->class == class_java_security_PrivilegedAction) {
882 CYCLES_STATS_END(stacktrace_getCurrentClass);
887 if (m->class != NULL) {
888 CYCLES_STATS_END(stacktrace_getCurrentClass);
894 /* No Java method found on the stack. */
896 CYCLES_STATS_END(stacktrace_getCurrentClass);
900 #endif /* ENABLE_JAVASE */
903 /* stacktrace_get_stack ********************************************************
905 Create a 2-dimensional array for java.security.VMAccessControler.
909 NULL if an exception has been thrown
911 *******************************************************************************/
913 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
914 java_handle_objectarray_t *stacktrace_get_stack(void)
916 stackframeinfo_t *sfi;
917 stackframeinfo_t tmpsfi;
919 java_handle_objectarray_t *oa;
920 java_handle_objectarray_t *classes;
921 java_handle_objectarray_t *methodnames;
923 java_handle_t *string;
926 CYCLES_STATS_DECLARE_AND_START
929 if (opt_DebugStackTrace)
930 log_println("[stacktrace_get_stack]");
933 /* Get the stackframeinfo of the current thread. */
935 sfi = threads_get_current_stackframeinfo();
937 /* Get the depth of the current stack. */
939 depth = stacktrace_depth(sfi);
944 /* Allocate the required arrays. */
946 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
951 classes = builtin_anewarray(depth, class_java_lang_Class);
956 methodnames = builtin_anewarray(depth, class_java_lang_String);
958 if (methodnames == NULL)
961 /* Set up the 2-dimensional array. */
963 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
964 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
966 /* Iterate over the whole stack. */
967 /* TODO We should use a critical section here to speed things
972 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
973 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
974 stacktrace_stackframeinfo_next(&tmpsfi)) {
975 /* Get the methodinfo. */
979 /* Skip builtin methods. */
981 if (m->flags & ACC_METHOD_BUILTIN)
984 /* Store the class in the array. */
985 /* NOTE: We use a LLNI-macro here, because a classinfo is not
988 LLNI_array_direct(classes, i) = (java_object_t *) m->class;
990 /* Store the name in the array. */
992 string = javastring_new(m->name);
997 array_objectarray_element_set(methodnames, i, string);
1002 CYCLES_STATS_END(stacktrace_get_stack)
1007 CYCLES_STATS_END(stacktrace_get_stack)
1014 /* stacktrace_print ************************************************************
1016 Print the given stacktrace with CACAO intern methods only (no Java
1019 This method is used by stacktrace_dump_trace and
1020 builtin_trace_exception.
1023 st ... stacktrace to print
1025 *******************************************************************************/
1027 void stacktrace_print(stacktrace_t *st)
1029 stacktrace_entry_t *ste;
1034 ste = &(st->entries[0]);
1036 for (i = 0; i < st->length; i++, ste++) {
1039 /* Get the line number. */
1041 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1044 utf_display_printable_ascii_classname(m->class->name);
1046 utf_display_printable_ascii(m->name);
1047 utf_display_printable_ascii(m->descriptor);
1049 if (m->flags & ACC_NATIVE) {
1050 puts("(Native Method)");
1054 utf_display_printable_ascii(m->class->sourcefile);
1055 printf(":%d)\n", linenumber);
1059 /* just to be sure */
1065 /* stacktrace_print_exception **************************************************
1067 Print the stacktrace of a given exception (more or less a wrapper
1068 to stacktrace_print).
1071 h ... handle of exception to print
1073 *******************************************************************************/
1075 void stacktrace_print_exception(java_handle_t *h)
1077 java_lang_Throwable *o;
1079 #if defined(WITH_CLASSPATH_GNU)
1080 java_lang_VMThrowable *vmt;
1081 gnu_classpath_Pointer *backtrace;
1082 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1083 java_lang_Object *backtrace;
1086 java_handle_bytearray_t *ba;
1089 o = (java_lang_Throwable *) h;
1094 /* now print the stacktrace */
1096 #if defined(WITH_CLASSPATH_GNU)
1098 LLNI_field_get_ref(o, vmState, vmt);
1099 LLNI_field_get_ref(vmt, vmData, backtrace);
1101 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1103 LLNI_field_get_ref(o, backtrace, backtrace);
1106 # error unknown classpath configuration
1109 ba = (java_handle_bytearray_t *) backtrace;
1115 /* We need a critical section here as we use the byte-array data
1116 pointer directly. */
1118 LLNI_CRITICAL_START;
1120 st = (stacktrace_t *) LLNI_array_data(ba);
1122 stacktrace_print(st);
1128 #if defined(ENABLE_CYCLES_STATS)
1129 void stacktrace_print_cycles_stats(FILE *file)
1131 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1132 CYCLES_STATS_PRINT(stacktrace_get, file);
1133 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1134 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1135 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1141 * These are local overrides for various environment variables in Emacs.
1142 * Please do not remove this and leave it at the end of the file, where
1143 * Emacs will automagically detect them.
1144 * ---------------------------------------------------------------------
1147 * indent-tabs-mode: t
1151 * vim:noexpandtab:sw=4:ts=4: