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
25 $Id: stacktrace.c 7246 2007-01-29 18:49:05Z twisti $
38 #include "mm/gc-common.h"
39 #include "mm/memory.h"
41 #include "vm/global.h" /* required here for native includes */
42 #include "native/jni.h"
43 #include "native/include/java_lang_Throwable.h"
45 #if defined(WITH_CLASSPATH_GNU)
46 # include "native/include/java_lang_VMThrowable.h"
49 #if defined(ENABLE_THREADS)
50 # include "threads/native/threads.h"
52 # include "threads/none/threads.h"
55 #include "toolbox/logging.h"
57 #include "vm/builtin.h"
58 #include "vm/cycles-stats.h"
59 #include "vm/exceptions.h"
60 #include "vm/stringlocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/methodheader.h"
67 #include "vmcore/class.h"
68 #include "vmcore/loader.h"
69 #include "vmcore/options.h"
72 /* global variables ***********************************************************/
74 #if !defined(ENABLE_THREADS)
75 stackframeinfo *_no_threads_stackframeinfo = NULL;
78 CYCLES_STATS_DECLARE(stacktrace_overhead ,100,1)
79 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace,40,5000)
80 CYCLES_STATS_DECLARE(stacktrace_getClassContext ,40,5000)
81 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass ,40,5000)
82 CYCLES_STATS_DECLARE(stacktrace_getStack ,40,10000)
85 /* stacktrace_create_stackframeinfo ********************************************
87 Creates an stackframe info structure for inline code in the
90 *******************************************************************************/
92 #if defined(ENABLE_INTRP)
93 void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
96 stackframeinfo **psfi;
100 /* get current stackframe info pointer */
102 psfi = STACKFRAMEINFO;
104 /* if we don't have pv handy */
107 #if defined(ENABLE_INTRP)
109 pv = codegen_get_pv_from_pc(ra);
113 #if defined(ENABLE_JIT)
114 pv = md_codegen_get_pv_from_pc(ra);
119 /* get codeinfo pointer from data segment */
121 code = *((codeinfo **) (pv + CodeinfoPointer));
123 /* For asm_vm_call_method the codeinfo pointer is NULL. */
125 m = (code == NULL) ? NULL : code->m;
127 /* fill new stackframe info structure */
135 /* xpc is the same as ra, but is required in stacktrace_create */
139 /* store new stackframe info pointer */
143 #endif /* defined(ENABLE_INTRP) */
146 /* stacktrace_create_inline_stackframeinfo *************************************
148 Creates an stackframe info structure for an inline exception stub.
150 *******************************************************************************/
152 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
153 u1 *sp, u1 *ra, u1 *xpc)
155 stackframeinfo **psfi;
157 /* get current stackframe info pointer */
159 psfi = STACKFRAMEINFO;
161 #if defined(ENABLE_INTRP)
163 /* if we don't have pv handy */
166 pv = codegen_get_pv_from_pc(ra);
171 /* fill new stackframe info structure */
180 /* store new stackframe info pointer */
186 /* stacktrace_create_extern_stackframeinfo *************************************
188 Creates an stackframe info structure for an extern exception
189 (hardware or assembler).
191 *******************************************************************************/
193 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
194 u1 *sp, u1 *ra, u1 *xpc)
196 stackframeinfo **psfi;
197 #if !defined(__I386__) && !defined(__X86_64__)
200 #if defined(ENABLE_JIT)
204 /* get current stackframe info pointer */
206 psfi = STACKFRAMEINFO;
208 /* sometimes we don't have pv handy (e.g. in asmpart.S:
209 L_asm_call_jit_compiler_exception or in the interpreter). */
212 #if defined(ENABLE_INTRP)
214 pv = codegen_get_pv_from_pc(ra);
218 #if defined(ENABLE_JIT)
219 pv = md_codegen_get_pv_from_pc(ra);
224 #if defined(ENABLE_JIT)
225 # if defined(ENABLE_INTRP)
226 /* When using the interpreter, we pass RA to the function. */
230 # if defined(__I386__) || defined(__X86_64__)
231 /* On i386 and x86_64 we always have to get the return address
234 framesize = *((u4 *) (pv + FrameSize));
236 ra = md_stacktrace_get_returnaddress(sp, framesize);
238 /* If the method is a non-leaf function, we need to get the return
239 address from the stack. For leaf functions the return address
240 is set correctly. This makes the assembler and the signal
241 handler code simpler. */
243 isleafmethod = *((s4 *) (pv + IsLeaf));
246 framesize = *((u4 *) (pv + FrameSize));
248 ra = md_stacktrace_get_returnaddress(sp, framesize);
251 # if defined(ENABLE_INTRP)
254 #endif /* defined(ENABLE_JIT) */
256 /* fill new stackframe info structure */
265 /* store new stackframe info pointer */
271 /* stacktrace_create_native_stackframeinfo *************************************
273 Creates a stackframe info structure for a native stub.
275 *******************************************************************************/
277 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
280 stackframeinfo **psfi;
284 /* get codeinfo pointer from data segment */
286 code = *((codeinfo **) (pv + CodeinfoPointer));
288 /* For asm_vm_call_method the codeinfo pointer is NULL. */
290 m = (code == NULL) ? NULL : code->m;
292 /* get current stackframe info pointer */
294 psfi = STACKFRAMEINFO;
296 /* fill new stackframe info structure */
305 /* store new stackframe info pointer */
311 /* stacktrace_remove_stackframeinfo ********************************************
313 Remove the topmost stackframeinfo in the current thread.
315 *******************************************************************************/
317 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
319 stackframeinfo **psfi;
321 /* get current stackframe info pointer */
323 psfi = STACKFRAMEINFO;
325 /* restore the old pointer */
331 /* stacktrace_inline_arithmeticexception ***************************************
333 Creates an ArithemticException for inline stub.
335 *******************************************************************************/
337 java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
341 java_objectheader *o;
343 /* create stackframeinfo */
345 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
347 /* create exception */
349 o = exceptions_new_arithmeticexception();
351 /* remove stackframeinfo */
353 stacktrace_remove_stackframeinfo(&sfi);
359 /* stacktrace_inline_arrayindexoutofboundsexception ****************************
361 Creates an ArrayIndexOutOfBoundsException for inline stub.
363 *******************************************************************************/
365 java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
372 java_objectheader *o;
374 /* create stackframeinfo */
376 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
378 /* create exception */
380 o = exceptions_new_arrayindexoutofboundsexception(index);
382 /* remove stackframeinfo */
384 stacktrace_remove_stackframeinfo(&sfi);
390 /* stacktrace_inline_arraystoreexception ***************************************
392 Creates an ArrayStoreException for inline stub.
394 *******************************************************************************/
396 java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
400 java_objectheader *o;
402 /* create stackframeinfo */
404 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
406 /* create exception */
408 o = exceptions_new_arraystoreexception();
410 /* remove stackframeinfo */
412 stacktrace_remove_stackframeinfo(&sfi);
418 /* stacktrace_inline_classcastexception ****************************************
420 Creates an ClassCastException for inline stub.
422 *******************************************************************************/
424 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
426 java_objectheader *o)
429 java_objectheader *e;
431 /* create stackframeinfo */
433 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
435 /* create exception */
437 e = exceptions_new_classcastexception(o);
439 /* remove stackframeinfo */
441 stacktrace_remove_stackframeinfo(&sfi);
447 /* stacktrace_inline_nullpointerexception **************************************
449 Creates an NullPointerException for inline stub.
451 *******************************************************************************/
453 java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
457 java_objectheader *o;
459 /* create stackframeinfo */
461 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
463 /* create exception */
465 o = exceptions_new_nullpointerexception();
467 /* remove stackframeinfo */
469 stacktrace_remove_stackframeinfo(&sfi);
475 /* stacktrace_inline_fillInStackTrace ******************************************
477 Fills in the correct stacktrace into an existing exception object
478 (this one is for inline exception stubs).
480 *******************************************************************************/
482 java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
486 java_objectheader *o;
489 /* create stackframeinfo */
491 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
498 /* clear exception */
500 *exceptionptr = NULL;
502 /* resolve methodinfo pointer from exception object */
504 #if defined(ENABLE_JAVASE)
505 m = class_resolvemethod(o->vftbl->class,
506 utf_fillInStackTrace,
507 utf_void__java_lang_Throwable);
508 #elif defined(ENABLE_JAVAME_CLDC1_1)
509 m = class_resolvemethod(o->vftbl->class,
510 utf_fillInStackTrace,
518 (void) vm_call_method(m, o);
520 /* remove stackframeinfo */
522 stacktrace_remove_stackframeinfo(&sfi);
528 /* stacktrace_hardware_arithmeticexception *************************************
530 Creates an ArithemticException for inline stub.
532 *******************************************************************************/
534 java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
538 java_objectheader *o;
540 /* create stackframeinfo */
542 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
544 /* create exception */
546 o = exceptions_new_arithmeticexception();
548 /* remove stackframeinfo */
550 stacktrace_remove_stackframeinfo(&sfi);
556 /* stacktrace_hardware_nullpointerexception ************************************
558 Creates an NullPointerException for the SIGSEGV signal handler.
560 *******************************************************************************/
562 java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
566 java_objectheader *o;
568 /* create stackframeinfo */
570 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
572 /* create exception */
574 o = exceptions_new_nullpointerexception();
576 /* remove stackframeinfo */
578 stacktrace_remove_stackframeinfo(&sfi);
584 /* stacktrace_add_entry ********************************************************
586 Adds a new entry to the stacktrace buffer.
588 *******************************************************************************/
590 static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
592 stacktrace_entry *ste;
594 /* check if we already reached the buffer capacity */
596 if (stb->used >= stb->capacity) {
597 /* reallocate new memory */
599 stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
600 stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
602 /* set new buffer capacity */
604 stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
607 /* insert the current entry */
609 ste = &(stb->entries[stb->used]);
612 ste->linenumber = line;
614 /* increase entries used count */
620 /* stacktrace_add_method *******************************************************
622 Add stacktrace entries[1] for the given method to the stacktrace buffer.
625 stb.........stacktracebuffer to fill
626 m...........method for which entries should be created
627 pv..........pv of method
628 pc..........position of program counter within the method's code
631 true, if stacktrace entries were successfully created, false otherwise.
633 [1] In case of inlined methods there may be more than one stacktrace
634 entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
636 *******************************************************************************/
638 static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
641 codeinfo *code; /* compiled realization of method */
644 /* find the realization of the method the pc is in */
646 code = *((codeinfo **) (pv + CodeinfoPointer));
648 /* search the line number table */
650 linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
652 /* now add a new entry to the staktrace */
654 stacktrace_add_entry(stb, m, linenumber);
660 /* stacktrace_create ***********************************************************
662 Generates a stacktrace from the thread passed into a
663 stacktracebuffer. The stacktracebuffer is allocated on the GC
667 pointer to the stacktracebuffer, or
668 NULL if an exception has been thrown
670 *******************************************************************************/
672 stacktracebuffer *stacktrace_create(threadobject* thread)
674 stacktracebuffer *stb;
684 /* prevent compiler warnings */
690 /* create a stacktracebuffer in dump memory */
692 stb = DNEW(stacktracebuffer);
694 stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
696 stb->entries = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
698 /* The first element in the stackframe chain must always be a
699 native stackframeinfo (VMThrowable.fillInStackTrace is a native
702 /* We don't use the STACKFRAMEINFO macro here, as we have to use
703 the passed thread. */
705 #if defined(ENABLE_THREADS)
706 sfi = thread->_stackframeinfo;
708 sfi = _no_threads_stackframeinfo;
711 #define PRINTMETHODS 0
714 printf("\n\nfillInStackTrace start:\n");
718 /* Loop while we have a method pointer (asm_calljavafunction has
719 NULL) or there is a stackframeinfo in the chain. */
723 while ((m != NULL) || (sfi != NULL)) {
724 /* m == NULL should only happen for the first time and inline
725 stackframe infos, like from the exception stubs or the
729 /* for native stub stackframe infos, pv is always NULL */
731 if (sfi->pv == NULL) {
732 /* get methodinfo, sp and ra from the current stackframe info */
735 sp = sfi->sp; /* sp of parent Java function */
739 stacktrace_add_entry(stb, m, 0);
742 printf("ra=%p sp=%p, ", ra, sp);
744 printf(": native stub\n");
747 /* This is an native stub stackframe info, so we can
748 get the parent pv from the return address
751 #if defined(ENABLE_INTRP)
753 pv = codegen_get_pv_from_pc(ra);
757 #if defined(ENABLE_JIT)
758 pv = md_codegen_get_pv_from_pc(ra);
762 /* get methodinfo pointer from parent data segment */
764 code = *((codeinfo **) (pv + CodeinfoPointer));
766 /* For asm_vm_call_method the codeinfo pointer is
769 m = (code == NULL) ? NULL : code->m;
772 /* Inline stackframe infos are special: they have a
773 xpc of the actual exception position and the return
774 address saved since an inline stackframe info can
775 also be in a leaf method (no return address saved
776 on stack!!!). ATTENTION: This one is also for
777 hardware exceptions!!! */
779 /* get methodinfo, sp and ra from the current stackframe info */
781 m = sfi->method; /* m == NULL */
782 pv = sfi->pv; /* pv of parent Java function */
783 sp = sfi->sp; /* sp of parent Java function */
784 ra = sfi->ra; /* ra of parent Java function */
785 xpc = sfi->xpc; /* actual exception position */
788 printf("ra=%p sp=%p, ", ra, sp);
789 printf("NULL: inline stub\n");
793 /* get methodinfo from current Java method */
795 code = *((codeinfo **) (pv + CodeinfoPointer));
797 /* For asm_vm_call_method the codeinfo pointer is
800 m = (code == NULL) ? NULL : code->m;
802 /* if m == NULL, this is a asm_calljavafunction call */
806 printf("ra=%p sp=%p, ", ra, sp);
808 printf(": inline stub parent");
812 #if defined(ENABLE_INTRP)
816 /* add the method to the stacktrace */
818 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
820 /* get the current stack frame size */
822 framesize = *((u4 *) (pv + FrameSize));
825 printf(", framesize=%d\n", framesize);
829 /* Set stack pointer to stackframe of parent Java
830 function of the current Java function. */
832 #if defined(__I386__) || defined (__X86_64__)
833 sp += framesize + SIZEOF_VOID_P;
838 /* get data segment and methodinfo pointer from
841 #if defined(ENABLE_JIT)
842 pv = md_codegen_get_pv_from_pc(ra);
845 code = *((codeinfo **) (pv + CodeinfoPointer));
847 /* For asm_vm_call_method the codeinfo pointer is
850 m = (code == NULL) ? NULL : code->m;
852 #if defined(ENABLE_INTRP)
858 printf("ra=%p sp=%p, ", ra, sp);
859 printf("asm_calljavafunction\n");
865 /* get previous stackframeinfo in the chain */
871 printf("ra=%p sp=%p, ", ra, sp);
877 /* JIT method found, add it to the stacktrace (we subtract
878 1 from the return address since it points the the
879 instruction after call). */
881 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
883 /* get the current stack frame size */
885 framesize = *((u4 *) (pv + FrameSize));
888 printf(", framesize=%d\n", framesize);
892 /* get return address of current stack frame */
894 #if defined(ENABLE_JIT)
895 # if defined(ENABLE_INTRP)
897 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
900 ra = md_stacktrace_get_returnaddress(sp, framesize);
902 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
905 /* get data segment and methodinfo pointer from parent method */
907 #if defined(ENABLE_INTRP)
909 pv = codegen_get_pv_from_pc(ra);
913 #if defined(ENABLE_JIT)
914 pv = md_codegen_get_pv_from_pc(ra);
918 code = *((codeinfo **) (pv + CodeinfoPointer));
920 /* For asm_vm_call_method the codeinfo pointer is NULL. */
922 m = (code == NULL) ? NULL : code->m;
926 #if defined(ENABLE_INTRP)
928 sp = *(u1 **) (sp - framesize);
932 #if defined(__I386__) || defined (__X86_64__)
933 sp += framesize + SIZEOF_VOID_P;
941 /* return the stacktracebuffer */
947 /* stacktrace_fillInStackTrace *************************************************
949 Generate a stacktrace from the current thread for
950 java.lang.VMThrowable.fillInStackTrace.
952 *******************************************************************************/
954 stacktracecontainer *stacktrace_fillInStackTrace(void)
956 stacktracebuffer *stb;
957 stacktracecontainer *gcstc;
960 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
962 /* mark start of dump memory area */
964 dumpsize = dump_size();
966 /* create a stacktrace from the current thread */
968 stb = stacktrace_create(THREADOBJECT);
972 /* allocate memory from the GC heap and copy the stacktrace buffer */
973 /* ATTENTION: use stacktracecontainer for this and make it look like
976 gcstc_size = sizeof(stacktracebuffer) +
977 sizeof(stacktrace_entry) * stb->used;
978 gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
983 gcstc->stb.capacity = stb->capacity;
984 gcstc->stb.used = stb->used;
985 gcstc->stb.entries = gcstc->data;
987 MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
989 /* release dump memory */
991 dump_release(dumpsize);
993 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
998 dump_release(dumpsize);
1000 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1001 stacktrace_overhead)
1007 /* stacktrace_getClassContext **************************************************
1009 Creates a Class context array.
1012 the array of java.lang.Class objects, or
1013 NULL if an exception has been thrown
1015 *******************************************************************************/
1017 java_objectarray *stacktrace_getClassContext(void)
1019 stacktracebuffer *stb;
1020 stacktrace_entry *ste;
1021 java_objectarray *oa;
1025 CYCLES_STATS_DECLARE_AND_START
1027 /* mark start of dump memory area */
1029 dumpsize = dump_size();
1031 /* create a stacktrace for the current thread */
1033 stb = stacktrace_create(THREADOBJECT);
1037 /* calculate the size of the Class array */
1039 for (i = 0, oalength = 0; i < stb->used; i++)
1040 if (stb->entries[i].method != NULL)
1043 /* The first entry corresponds to the method whose implementation */
1044 /* calls stacktrace_getClassContext. We remove that entry. */
1046 ste = &(stb->entries[0]);
1050 /* allocate the Class array */
1052 oa = builtin_anewarray(oalength, class_java_lang_Class);
1056 /* fill the Class array from the stacktracebuffer */
1058 for(i = 0; i < oalength; i++, ste++) {
1059 if (ste->method == NULL) {
1064 oa->data[i] = (java_objectheader *) ste->method->class;
1067 /* release dump memory */
1069 dump_release(dumpsize);
1071 CYCLES_STATS_END(stacktrace_getClassContext)
1076 dump_release(dumpsize);
1078 CYCLES_STATS_END(stacktrace_getClassContext)
1084 /* stacktrace_getCurrentClass **************************************************
1086 Find the current class by walking the stack trace.
1088 Quote from the JNI documentation:
1090 In the Java 2 Platform, FindClass locates the class loader
1091 associated with the current native method. If the native code
1092 belongs to a system class, no class loader will be
1093 involved. Otherwise, the proper class loader will be invoked to
1094 load and link the named class. When FindClass is called through the
1095 Invocation Interface, there is no current native method or its
1096 associated class loader. In that case, the result of
1097 ClassLoader.getBaseClassLoader is used."
1099 *******************************************************************************/
1101 #if defined(ENABLE_JAVASE)
1102 classinfo *stacktrace_getCurrentClass(void)
1104 stacktracebuffer *stb;
1105 stacktrace_entry *ste;
1109 CYCLES_STATS_DECLARE_AND_START
1111 /* mark start of dump memory area */
1113 dumpsize = dump_size();
1115 /* create a stacktrace for the current thread */
1117 stb = stacktrace_create(THREADOBJECT);
1119 goto return_NULL; /* XXX exception: how to distinguish from normal NULL return? */
1121 /* iterate over all stacktrace entries and find the first suitable
1124 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1130 if (m->class == class_java_security_PrivilegedAction)
1133 if (m->class != NULL) {
1134 dump_release(dumpsize);
1136 CYCLES_STATS_END(stacktrace_getCurrentClass)
1142 /* no Java method found on the stack */
1145 dump_release(dumpsize);
1147 CYCLES_STATS_END(stacktrace_getCurrentClass)
1151 #endif /* ENABLE_JAVASE */
1154 /* stacktrace_getStack *********************************************************
1156 Create a 2-dimensional array for java.security.VMAccessControler.
1160 NULL if an exception has been thrown
1162 *******************************************************************************/
1164 #if defined(ENABLE_JAVASE)
1165 java_objectarray *stacktrace_getStack(void)
1167 stacktracebuffer *stb;
1168 stacktrace_entry *ste;
1169 java_objectarray *oa;
1170 java_objectarray *classes;
1171 java_objectarray *methodnames;
1173 java_objectheader *string;
1176 CYCLES_STATS_DECLARE_AND_START
1178 /* mark start of dump memory area */
1180 dumpsize = dump_size();
1182 /* create a stacktrace for the current thread */
1184 stb = stacktrace_create(THREADOBJECT);
1189 /* get the first stacktrace entry */
1191 ste = &(stb->entries[0]);
1193 /* allocate all required arrays */
1195 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1200 classes = builtin_anewarray(stb->used, class_java_lang_Class);
1202 if (classes == NULL)
1205 methodnames = builtin_anewarray(stb->used, class_java_lang_String);
1207 if (methodnames == NULL)
1210 /* set up the 2-dimensional array */
1212 oa->data[0] = (java_objectheader *) classes;
1213 oa->data[1] = (java_objectheader *) methodnames;
1215 /* iterate over all stacktrace entries */
1217 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1218 c = ste->method->class;
1220 classes->data[i] = (java_objectheader *) c;
1222 string = javastring_new(ste->method->name);
1227 methodnames->data[i] = string;
1230 /* return the 2-dimensional array */
1232 dump_release(dumpsize);
1234 CYCLES_STATS_END(stacktrace_getStack)
1239 dump_release(dumpsize);
1241 CYCLES_STATS_END(stacktrace_getStack)
1245 #endif /* ENABLE_JAVASE */
1248 /* stacktrace_print_trace_from_buffer ******************************************
1250 Print the stacktrace of a given stacktracebuffer with CACAO intern
1251 methods (no Java help). This method is used by
1252 stacktrace_dump_trace and builtin_trace_exception.
1254 *******************************************************************************/
1256 void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
1258 stacktrace_entry *ste;
1262 ste = &(stb->entries[0]);
1264 for (i = 0; i < stb->used; i++, ste++) {
1268 utf_display_printable_ascii_classname(m->class->name);
1270 utf_display_printable_ascii(m->name);
1271 utf_display_printable_ascii(m->descriptor);
1273 if (m->flags & ACC_NATIVE) {
1274 puts("(Native Method)");
1278 utf_display_printable_ascii(m->class->sourcefile);
1279 printf(":%d)\n", (u4) ste->linenumber);
1283 /* just to be sure */
1289 /* stacktrace_dump_trace *******************************************************
1291 This method is call from signal_handler_sigusr1 to dump the
1292 stacktrace of the current thread to stdout.
1294 *******************************************************************************/
1296 void stacktrace_dump_trace(threadobject *thread)
1298 stacktracebuffer *stb;
1301 /* mark start of dump memory area */
1303 dumpsize = dump_size();
1305 /* create a stacktrace for the current thread */
1307 stb = stacktrace_create(thread);
1309 /* print stacktrace */
1312 stacktrace_print_trace_from_buffer(stb);
1314 puts("\t<<No stacktrace available>>");
1318 dump_release(dumpsize);
1322 /* stacktrace_print_trace ******************************************************
1324 Print the stacktrace of a given exception. More or less a wrapper
1325 to stacktrace_print_trace_from_buffer.
1327 *******************************************************************************/
1329 void stacktrace_print_trace(java_objectheader *xptr)
1331 java_lang_Throwable *t;
1332 #if defined(WITH_CLASSPATH_GNU)
1333 java_lang_VMThrowable *vmt;
1335 stacktracecontainer *stc;
1336 stacktracebuffer *stb;
1338 t = (java_lang_Throwable *) xptr;
1343 /* now print the stacktrace */
1345 #if defined(WITH_CLASSPATH_GNU)
1347 stc = (stacktracecontainer *) vmt->vmData;
1349 #elif defined(WITH_CLASSPATH_CLDC1_1)
1350 stc = (stacktracecontainer *) t->backtrace;
1354 stacktrace_print_trace_from_buffer(stb);
1358 #if defined(ENABLE_CYCLES_STATS)
1359 void stacktrace_print_cycles_stats(FILE *file)
1361 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead,file);
1362 CYCLES_STATS_PRINT(stacktrace_fillInStackTrace,file);
1363 CYCLES_STATS_PRINT(stacktrace_getClassContext ,file);
1364 CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,file);
1365 CYCLES_STATS_PRINT(stacktrace_getStack ,file);
1371 * These are local overrides for various environment variables in Emacs.
1372 * Please do not remove this and leave it at the end of the file, where
1373 * Emacs will automagically detect them.
1374 * ---------------------------------------------------------------------
1377 * indent-tabs-mode: t
1381 * vim:noexpandtab:sw=4:ts=4: