1 /* src/vm/jit/stacktrace.c - machine independent stacktrace system
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
39 #include "mm/gc-common.h"
40 #include "mm/memory.h"
42 #include "vm/jit/stacktrace.h"
44 #include "vm/global.h" /* required here for native includes */
45 #include "native/jni.h"
46 #include "native/llni.h"
47 #include "native/include/java_lang_Throwable.h"
49 #if defined(WITH_CLASSPATH_GNU)
50 # include "native/include/java_lang_VMThrowable.h"
53 #if defined(ENABLE_THREADS)
54 # include "threads/native/threads.h"
56 # include "threads/none/threads.h"
59 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
63 #include "vm/cycles-stats.h"
64 #include "vm/exceptions.h"
65 #include "vm/stringlocal.h"
68 #include "vm/jit/asmpart.h"
69 #include "vm/jit/codegen-common.h"
70 #include "vm/jit/linenumbertable.h"
71 #include "vm/jit/methodheader.h"
73 #include "vmcore/class.h"
74 #include "vmcore/loader.h"
75 #include "vmcore/options.h"
78 /* global variables ***********************************************************/
79 #if !defined(ENABLE_THREADS)
80 stackframeinfo_t *_no_threads_stackframeinfo = NULL;
83 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
84 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
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 **psfi;
102 #if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
105 #if defined(ENABLE_JIT)
109 /* get current stackframe info pointer */
111 psfi = &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 = codegen_get_pv_from_pc(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 return
158 address from the stack. For leaf functions the return address
159 is set correctly. This makes the assembler and the signal
160 handler code simpler. */
162 isleafmethod = *((s4 *) (pv + IsLeaf));
165 framesize = *((u4 *) (pv + FrameSize));
167 ra = md_stacktrace_get_returnaddress(sp, framesize);
170 # if defined(ENABLE_INTRP)
175 /* Calculate XPC when not given. The XPC is then the return
176 address of the current method minus 1 because the RA points to
177 the instruction after the call instruction. This is required
178 e.g. for method stubs. */
181 xpc = (void *) (((intptr_t) ra) - 1);
184 /* Fill new stackframeinfo structure. */
194 if (opt_DebugStackFrameInfo) {
196 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
197 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
198 method_print(sfi->code->m);
204 /* Store new stackframeinfo pointer. */
208 /* set the native world flag for the current thread */
209 /* ATTENTION: This flag tells the GC how to treat this thread in case of
210 a collection. Set this flag _after_ a valid stackframe info was set. */
212 THREAD_NATIVEWORLD_ENTER;
216 /* stacktrace_stackframeinfo_remove ********************************************
218 Remove the given stackframeinfo from the chain in the current
221 *******************************************************************************/
223 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
225 stackframeinfo_t **psfi;
227 /* clear the native world flag for the current thread */
228 /* ATTENTION: Clear this flag _before_ removing the stackframe info */
230 THREAD_NATIVEWORLD_EXIT;
232 /* get current stackframe info pointer */
234 psfi = &STACKFRAMEINFO;
237 if (opt_DebugStackFrameInfo) {
239 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
240 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
241 method_print(sfi->code->m);
247 /* restore the old pointer */
253 /* stacktrace_stackframeinfo_fill **********************************************
255 Fill the temporary stackframeinfo structure with the values given
259 tmpsfi ... temporary stackframeinfo
260 sfi ...... stackframeinfo to be used in the next iteration
262 *******************************************************************************/
264 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
268 assert(tmpsfi != NULL);
271 /* Fill the temporary stackframeinfo. */
273 tmpsfi->code = sfi->code;
274 tmpsfi->pv = sfi->pv;
275 tmpsfi->sp = sfi->sp;
276 tmpsfi->ra = sfi->ra;
277 tmpsfi->xpc = sfi->xpc;
279 /* Set the previous stackframe info of the temporary one to the
280 next in the chain. */
282 tmpsfi->prev = sfi->prev;
285 /* Print current method information. */
287 if (opt_DebugStackTrace) {
288 log_println("[stacktrace start]");
290 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
291 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
293 method_print(tmpsfi->code->m);
301 /* stacktrace_stackframeinfo_next **********************************************
303 Walk the stack (or the stackframeinfo-chain) to the next method and
304 return the new stackframe values in the temporary stackframeinfo
307 ATTENTION: This function does NOT skip builtin methods!
310 tmpsfi ... temporary stackframeinfo of current method
312 *******************************************************************************/
314 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
322 stackframeinfo_t *prevsfi;
326 assert(tmpsfi != NULL);
328 /* Get values from the stackframeinfo. */
336 /* Get the current stack frame size. */
338 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
340 /* Get the RA of the current stack frame (RA to the parent Java
341 method) if the current method is a non-leaf method. Otherwise
342 the value in the stackframeinfo is correct (from the signal
345 #if defined(ENABLE_JIT)
346 # if defined(ENABLE_INTRP)
348 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
352 if (!code_is_leafmethod(code))
353 ra = md_stacktrace_get_returnaddress(sp, framesize);
356 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
359 /* Get the PV for the parent Java method. */
361 #if defined(ENABLE_INTRP)
363 pv = codegen_get_pv_from_pc(ra);
367 #if defined(ENABLE_JIT)
368 # if defined(__SPARC_64__)
369 sp = md_get_framepointer(sp);
370 pv = md_get_pv_from_stackframe(sp);
372 pv = md_codegen_get_pv_from_pc(ra);
377 /* Get the codeinfo pointer for the parent Java method. */
379 code = code_get_codeinfo_for_pv(pv);
381 /* Calculate the SP for the parent Java method. */
383 #if defined(ENABLE_INTRP)
385 sp = *(u1 **) (sp - framesize);
389 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
390 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
391 #elif defined(__SPARC_64__)
392 /* already has the new sp */
394 sp = (void *) (((intptr_t) sp) + framesize);
398 /* If the new codeinfo pointer is NULL we reached a
399 asm_vm_call_method function. In this case we get the next
400 values from the previous stackframeinfo in the chain.
401 Otherwise the new values have been calculated before. */
404 prevsfi = tmpsfi->prev;
406 /* If the previous stackframeinfo in the chain is NULL we
407 reached the top of the stacktrace. We set code and prev to
408 NULL to mark the end, which is checked in
409 stacktrace_stackframeinfo_end_check. */
411 if (prevsfi == NULL) {
417 /* Fill the temporary stackframeinfo with the new values. */
419 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
422 /* Store the new values in the stackframeinfo. NOTE: We
423 subtract 1 from the RA to get the XPC, because the RA
424 points to the instruction after the call instruction. */
430 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
434 /* Print current method information. */
436 if (opt_DebugStackTrace) {
438 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
439 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
441 method_print(tmpsfi->code->m);
449 /* stacktrace_stackframeinfo_end_check *****************************************
451 Check if we reached the end of the stacktrace.
454 tmpsfi ... temporary stackframeinfo of current method
457 true .... the end is reached
458 false ... the end is not reached
460 *******************************************************************************/
462 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
466 assert(tmpsfi != NULL);
468 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
470 if (opt_DebugStackTrace)
471 log_println("[stacktrace stop]");
481 /* stacktrace_depth ************************************************************
483 Calculates and returns the depth of the current stacktrace.
486 sfi ... stackframeinfo where to start the stacktrace
489 depth of the stacktrace
491 *******************************************************************************/
493 static int stacktrace_depth(stackframeinfo_t *sfi)
495 stackframeinfo_t tmpsfi;
500 if (opt_DebugStackTrace)
501 log_println("[stacktrace_depth]");
504 /* XXX This is not correct, but a workaround for threads-dump for
506 /* assert(sfi != NULL); */
510 /* Iterate over all stackframes. */
514 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
515 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
516 stacktrace_stackframeinfo_next(&tmpsfi)) {
517 /* Get methodinfo. */
521 /* Skip builtin methods. */
523 if (m->flags & ACC_METHOD_BUILTIN)
533 /* stacktrace_get **************************************************************
535 Builds and returns a stacktrace from the current thread for and
536 returns the stacktrace structure wrapped in a Java byte-array to
540 stacktrace as Java byte-array
542 *******************************************************************************/
544 java_handle_bytearray_t *stacktrace_get(void)
546 stackframeinfo_t *sfi;
547 stackframeinfo_t tmpsfi;
549 java_handle_bytearray_t *ba;
552 stacktrace_entry_t *ste;
554 bool skip_fillInStackTrace;
557 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
560 if (opt_DebugStackTrace)
561 log_println("[stacktrace_get]");
564 skip_fillInStackTrace = true;
567 /* Get the stacktrace depth of the current thread. */
569 sfi = STACKFRAMEINFO;
571 depth = stacktrace_depth(sfi);
576 /* Allocate memory from the GC heap and copy the stacktrace
578 /* ATTENTION: Use a Java byte-array for this to not confuse the
580 /* FIXME: We waste some memory here as we skip some entries
583 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
585 ba = builtin_newarray_byte(ba_size);
590 /* Get a stacktrace entry pointer. */
591 /* ATTENTION: We need a critical section here because we use the
592 byte-array data pointer directly. */
596 st = (stacktrace_t *) LLNI_array_data(ba);
600 /* Iterate over the whole stack. */
602 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
603 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
604 stacktrace_stackframeinfo_next(&tmpsfi)) {
605 /* Get the methodinfo. */
609 /* Skip builtin methods. */
611 if (m->flags & ACC_METHOD_BUILTIN)
614 /* This logic is taken from
615 hotspot/src/share/vm/classfile/javaClasses.cpp
616 (java_lang_Throwable::fill_in_stack_trace). */
618 if (skip_fillInStackTrace == true) {
619 /* Check "fillInStackTrace" only once, so we negate the
620 flag after the first time check. */
622 #if defined(WITH_CLASSPATH_GNU)
623 /* For GNU Classpath we also need to skip
624 VMThrowable.fillInStackTrace(). */
626 if ((m->class == class_java_lang_VMThrowable) &&
627 (m->name == utf_fillInStackTrace))
631 skip_fillInStackTrace = false;
633 if (m->name == utf_fillInStackTrace)
637 /* Skip <init> methods of the exceptions klass. If there is
638 <init> methods that belongs to a superclass of the
639 exception we are going to skipping them in stack trace. */
641 if (skip_init == true) {
642 if (m->name == utf_init) {
643 /* throwable->is_a(method->method_holder())) { */
647 /* If no "Throwable.init()" method found, we stop
648 checking it next time. */
654 /* Store the stacktrace entry and increment the pointer. */
656 ste->code = tmpsfi.code;
657 ste->pc = tmpsfi.xpc;
662 /* Store the number of entries in the stacktrace structure. */
664 st->length = ste - st->entries;
668 /* release dump memory */
670 /* dump_release(dumpsize); */
672 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
677 /* dump_release(dumpsize); */
679 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
686 /* stacktrace_first_nonnull_classloader ****************************************
688 Returns the first non-null (user-defined) classloader on the stack.
689 If none is found NULL is returned.
694 *******************************************************************************/
696 classloader *stacktrace_first_nonnull_classloader(void)
698 stackframeinfo_t *sfi;
699 stackframeinfo_t tmpsfi;
704 if (opt_DebugStackTrace)
705 log_println("[stacktrace_first_nonnull_classloader]");
708 /* Get the stackframeinfo of the current thread. */
710 sfi = STACKFRAMEINFO;
712 /* Iterate over the whole stack. */
714 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
715 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
716 stacktrace_stackframeinfo_next(&tmpsfi)) {
719 cl = class_get_classloader(m->class);
729 /* stacktrace_getClassContext **************************************************
731 Creates a Class context array.
734 the array of java.lang.Class objects, or
735 NULL if an exception has been thrown
737 *******************************************************************************/
739 java_handle_objectarray_t *stacktrace_getClassContext(void)
741 stackframeinfo_t *sfi;
742 stackframeinfo_t tmpsfi;
744 java_handle_objectarray_t *oa;
745 java_object_t **data;
749 CYCLES_STATS_DECLARE_AND_START
752 if (opt_DebugStackTrace)
753 log_println("[stacktrace_getClassContext]");
756 sfi = STACKFRAMEINFO;
758 /* Get the depth of the current stack. */
760 depth = stacktrace_depth(sfi);
762 /* The first stackframe corresponds to the method whose
763 implementation calls this native function. We remove that
767 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
768 stacktrace_stackframeinfo_next(&tmpsfi);
770 /* Allocate the Class array. */
772 oa = builtin_anewarray(depth, class_java_lang_Class);
775 CYCLES_STATS_END(stacktrace_getClassContext);
780 /* Fill the Class array from the stacktrace list. */
784 data = LLNI_array_data(oa);
786 /* Iterate over the whole stack. */
791 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
792 stacktrace_stackframeinfo_next(&tmpsfi)) {
793 /* Get methodinfo. */
797 /* Skip builtin methods. */
799 if (m->flags & ACC_METHOD_BUILTIN)
802 /* Store the class in the array. */
804 data[i] = (java_object_t *) m->class;
811 CYCLES_STATS_END(stacktrace_getClassContext)
817 /* stacktrace_getCurrentClass **************************************************
819 Find the current class by walking the stack trace.
821 Quote from the JNI documentation:
823 In the Java 2 Platform, FindClass locates the class loader
824 associated with the current native method. If the native code
825 belongs to a system class, no class loader will be
826 involved. Otherwise, the proper class loader will be invoked to
827 load and link the named class. When FindClass is called through the
828 Invocation Interface, there is no current native method or its
829 associated class loader. In that case, the result of
830 ClassLoader.getBaseClassLoader is used."
832 *******************************************************************************/
834 #if defined(ENABLE_JAVASE)
835 classinfo *stacktrace_get_current_class(void)
837 stackframeinfo_t *sfi;
838 stackframeinfo_t tmpsfi;
841 CYCLES_STATS_DECLARE_AND_START;
844 if (opt_DebugStackTrace)
845 log_println("[stacktrace_get_current_class]");
848 /* Get the stackframeinfo of the current thread. */
850 sfi = STACKFRAMEINFO;
852 /* If the stackframeinfo is NULL then FindClass is called through
853 the Invocation Interface and we return NULL */
856 CYCLES_STATS_END(stacktrace_getCurrentClass);
861 /* Iterate over the whole stack. */
863 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
864 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
865 stacktrace_stackframeinfo_next(&tmpsfi)) {
866 /* Get the methodinfo. */
870 if (m->class == class_java_security_PrivilegedAction) {
871 CYCLES_STATS_END(stacktrace_getCurrentClass);
876 if (m->class != NULL) {
877 CYCLES_STATS_END(stacktrace_getCurrentClass);
883 /* No Java method found on the stack. */
885 CYCLES_STATS_END(stacktrace_getCurrentClass);
889 #endif /* ENABLE_JAVASE */
892 /* stacktrace_get_stack ********************************************************
894 Create a 2-dimensional array for java.security.VMAccessControler.
898 NULL if an exception has been thrown
900 *******************************************************************************/
902 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
903 java_handle_objectarray_t *stacktrace_get_stack(void)
905 stackframeinfo_t *sfi;
906 stackframeinfo_t tmpsfi;
908 java_handle_objectarray_t *oa;
909 java_handle_objectarray_t *classes;
910 java_handle_objectarray_t *methodnames;
912 java_handle_t *string;
915 CYCLES_STATS_DECLARE_AND_START
918 if (opt_DebugStackTrace)
919 log_println("[stacktrace_get_stack]");
922 /* Get the stackframeinfo of the current thread. */
924 sfi = STACKFRAMEINFO;
926 /* Get the depth of the current stack. */
928 depth = stacktrace_depth(sfi);
933 /* Allocate the required arrays. */
935 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
940 classes = builtin_anewarray(depth, class_java_lang_Class);
945 methodnames = builtin_anewarray(depth, class_java_lang_String);
947 if (methodnames == NULL)
950 /* Set up the 2-dimensional array. */
952 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
953 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
955 /* Iterate over the whole stack. */
956 /* TODO We should use a critical section here to speed things
961 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
962 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
963 stacktrace_stackframeinfo_next(&tmpsfi)) {
964 /* Get the methodinfo. */
968 /* Skip builtin methods. */
970 if (m->flags & ACC_METHOD_BUILTIN)
973 /* Store the class in the array. */
974 /* NOTE: We use a LLNI-macro here, because a classinfo is not
977 LLNI_array_direct(classes, i) = (java_object_t *) m->class;
979 /* Store the name in the array. */
981 string = javastring_new(m->name);
986 array_objectarray_element_set(methodnames, i, string);
991 CYCLES_STATS_END(stacktrace_get_stack)
996 CYCLES_STATS_END(stacktrace_get_stack)
1003 /* stacktrace_print ************************************************************
1005 Print the given stacktrace with CACAO intern methods only (no Java
1008 This method is used by stacktrace_dump_trace and
1009 builtin_trace_exception.
1012 st ... stacktrace to print
1014 *******************************************************************************/
1016 void stacktrace_print(stacktrace_t *st)
1018 stacktrace_entry_t *ste;
1023 ste = &(st->entries[0]);
1025 for (i = 0; i < st->length; i++, ste++) {
1028 /* Get the line number. */
1030 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1033 utf_display_printable_ascii_classname(m->class->name);
1035 utf_display_printable_ascii(m->name);
1036 utf_display_printable_ascii(m->descriptor);
1038 if (m->flags & ACC_NATIVE) {
1039 puts("(Native Method)");
1043 utf_display_printable_ascii(m->class->sourcefile);
1044 printf(":%d)\n", linenumber);
1048 /* just to be sure */
1054 /* stacktrace_print_exception **************************************************
1056 Print the stacktrace of a given exception (more or less a wrapper
1057 to stacktrace_print).
1060 h ... handle of exception to print
1062 *******************************************************************************/
1064 void stacktrace_print_exception(java_handle_t *h)
1066 java_lang_Throwable *o;
1067 #if defined(WITH_CLASSPATH_GNU)
1068 java_lang_VMThrowable *vmt;
1070 java_handle_bytearray_t *ba;
1073 o = (java_lang_Throwable *) h;
1078 /* now print the stacktrace */
1080 #if defined(WITH_CLASSPATH_GNU)
1082 LLNI_field_get_ref(o, vmState, vmt);
1083 LLNI_field_get_ref(vmt, vmData, ba);
1085 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1087 LLNI_field_get_ref(o, backtrace, ba);
1090 # error unknown classpath configuration
1097 /* We need a critical section here as we use the byte-array data
1098 pointer directly. */
1100 LLNI_CRITICAL_START;
1102 st = (stacktrace_t *) LLNI_array_data(ba);
1104 stacktrace_print(st);
1110 #if defined(ENABLE_CYCLES_STATS)
1111 void stacktrace_print_cycles_stats(FILE *file)
1113 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1114 CYCLES_STATS_PRINT(stacktrace_get, file);
1115 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1116 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1117 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1123 * These are local overrides for various environment variables in Emacs.
1124 * Please do not remove this and leave it at the end of the file, where
1125 * Emacs will automagically detect them.
1126 * ---------------------------------------------------------------------
1129 * indent-tabs-mode: t
1133 * vim:noexpandtab:sw=4:ts=4: