1 /* src/vm/jit/stacktrace.c - machine independent stacktrace system
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Joseph Wenninger
31 $Id: stacktrace.c 6248 2006-12-27 22:39:39Z twisti $
44 #include "mm/gc-common.h"
45 #include "mm/memory.h"
46 #include "native/native.h"
48 #include "vm/global.h" /* required here for native includes */
49 #include "native/include/java_lang_Throwable.h"
51 #if defined(WITH_CLASSPATH_GNU)
52 # include "native/include/java_lang_VMThrowable.h"
55 #if defined(ENABLE_THREADS)
56 # include "threads/native/threads.h"
58 # include "threads/none/threads.h"
61 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
64 #include "vm/exceptions.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/stringlocal.h"
69 #include "vm/jit/asmpart.h"
70 #include "vm/jit/codegen-common.h"
71 #include "vm/jit/methodheader.h"
72 #include "vm/cycles-stats.h"
75 /* global variables ***********************************************************/
77 #if !defined(ENABLE_THREADS)
78 stackframeinfo *_no_threads_stackframeinfo = NULL;
81 CYCLES_STATS_DECLARE(stacktrace_overhead ,100,1)
82 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace,40,5000)
83 CYCLES_STATS_DECLARE(stacktrace_getClassContext ,40,5000)
84 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass ,40,5000)
85 CYCLES_STATS_DECLARE(stacktrace_getStack ,40,10000)
88 /* stacktrace_create_stackframeinfo ********************************************
90 Creates an stackframe info structure for inline code in the
93 *******************************************************************************/
95 #if defined(ENABLE_INTRP)
96 void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
99 stackframeinfo **psfi;
103 /* get current stackframe info pointer */
105 psfi = STACKFRAMEINFO;
107 /* if we don't have pv handy */
110 #if defined(ENABLE_INTRP)
112 pv = codegen_get_pv_from_pc(ra);
116 #if defined(ENABLE_JIT)
117 pv = md_codegen_get_pv_from_pc(ra);
122 /* get codeinfo pointer from data segment */
124 code = *((codeinfo **) (pv + CodeinfoPointer));
126 /* For asm_vm_call_method the codeinfo pointer is NULL. */
128 m = (code == NULL) ? NULL : code->m;
130 /* fill new stackframe info structure */
138 /* xpc is the same as ra, but is required in stacktrace_create */
142 /* store new stackframe info pointer */
146 #endif /* defined(ENABLE_INTRP) */
149 /* stacktrace_create_inline_stackframeinfo *************************************
151 Creates an stackframe info structure for an inline exception stub.
153 *******************************************************************************/
155 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
156 u1 *sp, u1 *ra, u1 *xpc)
158 stackframeinfo **psfi;
160 /* get current stackframe info pointer */
162 psfi = STACKFRAMEINFO;
164 #if defined(ENABLE_INTRP)
166 /* if we don't have pv handy */
169 pv = codegen_get_pv_from_pc(ra);
174 /* fill new stackframe info structure */
183 /* store new stackframe info pointer */
189 /* stacktrace_create_extern_stackframeinfo *************************************
191 Creates an stackframe info structure for an extern exception
192 (hardware or assembler).
194 *******************************************************************************/
196 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
197 u1 *sp, u1 *ra, u1 *xpc)
199 stackframeinfo **psfi;
200 #if !defined(__I386__) && !defined(__X86_64__)
203 #if defined(ENABLE_JIT)
207 /* get current stackframe info pointer */
209 psfi = STACKFRAMEINFO;
211 /* sometimes we don't have pv handy (e.g. in asmpart.S:
212 L_asm_call_jit_compiler_exception or in the interpreter). */
215 #if defined(ENABLE_INTRP)
217 pv = codegen_get_pv_from_pc(ra);
221 #if defined(ENABLE_JIT)
222 pv = md_codegen_get_pv_from_pc(ra);
227 #if defined(ENABLE_JIT)
228 # if defined(ENABLE_INTRP)
229 /* When using the interpreter, we pass RA to the function. */
233 # if defined(__I386__) || defined(__X86_64__)
234 /* On i386 and x86_64 we always have to get the return address
237 framesize = *((u4 *) (pv + FrameSize));
239 ra = md_stacktrace_get_returnaddress(sp, framesize);
241 /* If the method is a non-leaf function, we need to get the return
242 address from the stack. For leaf functions the return address
243 is set correctly. This makes the assembler and the signal
244 handler code simpler. */
246 isleafmethod = *((s4 *) (pv + IsLeaf));
249 framesize = *((u4 *) (pv + FrameSize));
251 ra = md_stacktrace_get_returnaddress(sp, framesize);
254 # if defined(ENABLE_INTRP)
257 #endif /* defined(ENABLE_JIT) */
259 /* fill new stackframe info structure */
268 /* store new stackframe info pointer */
274 /* stacktrace_create_native_stackframeinfo *************************************
276 Creates a stackframe info structure for a native stub.
278 *******************************************************************************/
280 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
283 stackframeinfo **psfi;
287 /* get codeinfo pointer from data segment */
289 code = *((codeinfo **) (pv + CodeinfoPointer));
291 /* For asm_vm_call_method the codeinfo pointer is NULL. */
293 m = (code == NULL) ? NULL : code->m;
295 /* get current stackframe info pointer */
297 psfi = STACKFRAMEINFO;
299 /* fill new stackframe info structure */
308 /* store new stackframe info pointer */
314 /* stacktrace_remove_stackframeinfo ********************************************
316 Remove the topmost stackframeinfo in the current thread.
318 *******************************************************************************/
320 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
322 stackframeinfo **psfi;
324 /* get current stackframe info pointer */
326 psfi = STACKFRAMEINFO;
328 /* restore the old pointer */
334 /* stacktrace_inline_arithmeticexception ***************************************
336 Creates an ArithemticException for inline stub.
338 *******************************************************************************/
340 java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
344 java_objectheader *o;
346 /* create stackframeinfo */
348 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
350 /* create exception */
352 o = new_arithmeticexception();
354 /* remove stackframeinfo */
356 stacktrace_remove_stackframeinfo(&sfi);
362 /* stacktrace_inline_arrayindexoutofboundsexception ****************************
364 Creates an ArrayIndexOutOfBoundsException for inline stub.
366 *******************************************************************************/
368 java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
375 java_objectheader *o;
377 /* create stackframeinfo */
379 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
381 /* create exception */
383 o = new_arrayindexoutofboundsexception(index);
385 /* remove stackframeinfo */
387 stacktrace_remove_stackframeinfo(&sfi);
393 /* stacktrace_inline_arraystoreexception ***************************************
395 Creates an ArrayStoreException for inline stub.
397 *******************************************************************************/
399 java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
403 java_objectheader *o;
405 /* create stackframeinfo */
407 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
409 /* create exception */
411 o = exceptions_new_arraystoreexception();
413 /* remove stackframeinfo */
415 stacktrace_remove_stackframeinfo(&sfi);
421 /* stacktrace_inline_classcastexception ****************************************
423 Creates an ClassCastException for inline stub.
425 *******************************************************************************/
427 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
429 java_objectheader *o)
432 java_objectheader *e;
434 /* create stackframeinfo */
436 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
438 /* create exception */
440 e = exceptions_new_classcastexception(o);
442 /* remove stackframeinfo */
444 stacktrace_remove_stackframeinfo(&sfi);
450 /* stacktrace_inline_nullpointerexception **************************************
452 Creates an NullPointerException for inline stub.
454 *******************************************************************************/
456 java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
460 java_objectheader *o;
462 /* create stackframeinfo */
464 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
466 /* create exception */
468 o = exceptions_new_nullpointerexception();
470 /* remove stackframeinfo */
472 stacktrace_remove_stackframeinfo(&sfi);
478 /* stacktrace_inline_fillInStackTrace ******************************************
480 Fills in the correct stacktrace into an existing exception object
481 (this one is for inline exception stubs).
483 *******************************************************************************/
485 java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
489 java_objectheader *o;
492 /* create stackframeinfo */
494 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
501 /* clear exception */
503 *exceptionptr = NULL;
505 /* resolve methodinfo pointer from exception object */
507 #if defined(ENABLE_JAVASE)
508 m = class_resolvemethod(o->vftbl->class,
509 utf_fillInStackTrace,
510 utf_void__java_lang_Throwable);
511 #elif defined(ENABLE_JAVAME_CLDC1_1)
512 m = class_resolvemethod(o->vftbl->class,
513 utf_fillInStackTrace,
521 (void) vm_call_method(m, o);
523 /* remove stackframeinfo */
525 stacktrace_remove_stackframeinfo(&sfi);
531 /* stacktrace_hardware_arithmeticexception *************************************
533 Creates an ArithemticException for inline stub.
535 *******************************************************************************/
537 java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
541 java_objectheader *o;
543 /* create stackframeinfo */
545 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
547 /* create exception */
549 o = new_arithmeticexception();
551 /* remove stackframeinfo */
553 stacktrace_remove_stackframeinfo(&sfi);
559 /* stacktrace_hardware_nullpointerexception ************************************
561 Creates an NullPointerException for the SIGSEGV signal handler.
563 *******************************************************************************/
565 java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
569 java_objectheader *o;
571 /* create stackframeinfo */
573 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
575 /* create exception */
577 o = exceptions_new_nullpointerexception();
579 /* remove stackframeinfo */
581 stacktrace_remove_stackframeinfo(&sfi);
587 /* stacktrace_add_entry ********************************************************
589 Adds a new entry to the stacktrace buffer.
591 *******************************************************************************/
593 static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
595 stacktrace_entry *ste;
597 /* check if we already reached the buffer capacity */
599 if (stb->used >= stb->capacity) {
600 /* reallocate new memory */
602 stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
603 stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
605 /* set new buffer capacity */
607 stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
610 /* insert the current entry */
612 ste = &(stb->entries[stb->used]);
615 ste->linenumber = line;
617 /* increase entries used count */
623 /* stacktrace_add_method *******************************************************
625 Add stacktrace entries[1] for the given method to the stacktrace buffer.
628 stb.........stacktracebuffer to fill
629 m...........method for which entries should be created
630 pv..........pv of method
631 pc..........position of program counter within the method's code
634 true, if stacktrace entries were successfully created, false otherwise.
636 [1] In case of inlined methods there may be more than one stacktrace
637 entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
639 *******************************************************************************/
641 static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
644 codeinfo *code; /* compiled realization of method */
647 /* find the realization of the method the pc is in */
649 code = *((codeinfo **) (pv + CodeinfoPointer));
651 /* search the line number table */
653 linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
655 /* now add a new entry to the staktrace */
657 stacktrace_add_entry(stb, m, linenumber);
663 /* stacktrace_create ***********************************************************
665 Generates a stacktrace from the thread passed into a
666 stacktracebuffer. The stacktracebuffer is allocated on the GC
670 pointer to the stacktracebuffer, or
671 NULL if an exception has been thrown
673 *******************************************************************************/
675 stacktracebuffer *stacktrace_create(threadobject* thread)
677 stacktracebuffer *stb;
687 /* prevent compiler warnings */
693 /* create a stacktracebuffer in dump memory */
695 stb = DNEW(stacktracebuffer);
697 stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
699 stb->entries = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
701 /* The first element in the stackframe chain must always be a
702 native stackframeinfo (VMThrowable.fillInStackTrace is a native
705 /* We don't use the STACKFRAMEINFO macro here, as we have to use
706 the passed thread. */
708 #if defined(ENABLE_THREADS)
709 sfi = thread->_stackframeinfo;
711 sfi = _no_threads_stackframeinfo;
714 #define PRINTMETHODS 0
717 printf("\n\nfillInStackTrace start:\n");
721 /* Loop while we have a method pointer (asm_calljavafunction has
722 NULL) or there is a stackframeinfo in the chain. */
726 while ((m != NULL) || (sfi != NULL)) {
727 /* m == NULL should only happen for the first time and inline
728 stackframe infos, like from the exception stubs or the
732 /* for native stub stackframe infos, pv is always NULL */
734 if (sfi->pv == NULL) {
735 /* get methodinfo, sp and ra from the current stackframe info */
738 sp = sfi->sp; /* sp of parent Java function */
742 stacktrace_add_entry(stb, m, 0);
745 printf("ra=%p sp=%p, ", ra, sp);
747 printf(": native stub\n");
750 /* This is an native stub stackframe info, so we can
751 get the parent pv from the return address
754 #if defined(ENABLE_INTRP)
756 pv = codegen_get_pv_from_pc(ra);
760 #if defined(ENABLE_JIT)
761 pv = md_codegen_get_pv_from_pc(ra);
765 /* get methodinfo pointer from parent data segment */
767 code = *((codeinfo **) (pv + CodeinfoPointer));
769 /* For asm_vm_call_method the codeinfo pointer is
772 m = (code == NULL) ? NULL : code->m;
775 /* Inline stackframe infos are special: they have a
776 xpc of the actual exception position and the return
777 address saved since an inline stackframe info can
778 also be in a leaf method (no return address saved
779 on stack!!!). ATTENTION: This one is also for
780 hardware exceptions!!! */
782 /* get methodinfo, sp and ra from the current stackframe info */
784 m = sfi->method; /* m == NULL */
785 pv = sfi->pv; /* pv of parent Java function */
786 sp = sfi->sp; /* sp of parent Java function */
787 ra = sfi->ra; /* ra of parent Java function */
788 xpc = sfi->xpc; /* actual exception position */
791 printf("ra=%p sp=%p, ", ra, sp);
792 printf("NULL: inline stub\n");
796 /* get methodinfo from current Java method */
798 code = *((codeinfo **) (pv + CodeinfoPointer));
800 /* For asm_vm_call_method the codeinfo pointer is
803 m = (code == NULL) ? NULL : code->m;
805 /* if m == NULL, this is a asm_calljavafunction call */
809 printf("ra=%p sp=%p, ", ra, sp);
811 printf(": inline stub parent");
815 #if defined(ENABLE_INTRP)
819 /* add the method to the stacktrace */
821 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
823 /* get the current stack frame size */
825 framesize = *((u4 *) (pv + FrameSize));
828 printf(", framesize=%d\n", framesize);
832 /* Set stack pointer to stackframe of parent Java
833 function of the current Java function. */
835 #if defined(__I386__) || defined (__X86_64__)
836 sp += framesize + SIZEOF_VOID_P;
841 /* get data segment and methodinfo pointer from
844 #if defined(ENABLE_JIT)
845 pv = md_codegen_get_pv_from_pc(ra);
848 code = *((codeinfo **) (pv + CodeinfoPointer));
850 /* For asm_vm_call_method the codeinfo pointer is
853 m = (code == NULL) ? NULL : code->m;
855 #if defined(ENABLE_INTRP)
861 printf("ra=%p sp=%p, ", ra, sp);
862 printf("asm_calljavafunction\n");
868 /* get previous stackframeinfo in the chain */
874 printf("ra=%p sp=%p, ", ra, sp);
880 /* JIT method found, add it to the stacktrace (we subtract
881 1 from the return address since it points the the
882 instruction after call). */
884 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
886 /* get the current stack frame size */
888 framesize = *((u4 *) (pv + FrameSize));
891 printf(", framesize=%d\n", framesize);
895 /* get return address of current stack frame */
897 #if defined(ENABLE_JIT)
898 # if defined(ENABLE_INTRP)
900 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
903 ra = md_stacktrace_get_returnaddress(sp, framesize);
905 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
908 /* get data segment and methodinfo pointer from parent method */
910 #if defined(ENABLE_INTRP)
912 pv = codegen_get_pv_from_pc(ra);
916 #if defined(ENABLE_JIT)
917 pv = md_codegen_get_pv_from_pc(ra);
921 code = *((codeinfo **) (pv + CodeinfoPointer));
923 /* For asm_vm_call_method the codeinfo pointer is NULL. */
925 m = (code == NULL) ? NULL : code->m;
929 #if defined(ENABLE_INTRP)
931 sp = *(u1 **) (sp - framesize);
935 #if defined(__I386__) || defined (__X86_64__)
936 sp += framesize + SIZEOF_VOID_P;
944 /* return the stacktracebuffer */
950 /* stacktrace_fillInStackTrace *************************************************
952 Generate a stacktrace from the current thread for
953 java.lang.VMThrowable.fillInStackTrace.
955 *******************************************************************************/
957 stacktracecontainer *stacktrace_fillInStackTrace(void)
959 stacktracebuffer *stb;
960 stacktracecontainer *gcstc;
963 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
965 /* mark start of dump memory area */
967 dumpsize = dump_size();
969 /* create a stacktrace from the current thread */
971 stb = stacktrace_create(THREADOBJECT);
975 /* allocate memory from the GC heap and copy the stacktrace buffer */
976 /* ATTENTION: use stacktracecontainer for this and make it look like
979 gcstc_size = sizeof(stacktracebuffer) +
980 sizeof(stacktrace_entry) * stb->used;
981 gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
986 gcstc->stb.capacity = stb->capacity;
987 gcstc->stb.used = stb->used;
988 gcstc->stb.entries = gcstc->data;
990 MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
992 /* release dump memory */
994 dump_release(dumpsize);
996 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1001 dump_release(dumpsize);
1003 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1004 stacktrace_overhead)
1010 /* stacktrace_getClassContext **************************************************
1012 Creates a Class context array.
1015 the array of java.lang.Class objects, or
1016 NULL if an exception has been thrown
1018 *******************************************************************************/
1020 java_objectarray *stacktrace_getClassContext(void)
1022 stacktracebuffer *stb;
1023 stacktrace_entry *ste;
1024 java_objectarray *oa;
1028 CYCLES_STATS_DECLARE_AND_START
1030 /* mark start of dump memory area */
1032 dumpsize = dump_size();
1034 /* create a stacktrace for the current thread */
1036 stb = stacktrace_create(THREADOBJECT);
1040 /* calculate the size of the Class array */
1042 for (i = 0, oalength = 0; i < stb->used; i++)
1043 if (stb->entries[i].method != NULL)
1046 /* The first entry corresponds to the method whose implementation */
1047 /* calls stacktrace_getClassContext. We remove that entry. */
1049 ste = &(stb->entries[0]);
1053 /* allocate the Class array */
1055 oa = builtin_anewarray(oalength, class_java_lang_Class);
1059 /* fill the Class array from the stacktracebuffer */
1061 for(i = 0; i < oalength; i++, ste++) {
1062 if (ste->method == NULL) {
1067 oa->data[i] = (java_objectheader *) ste->method->class;
1070 /* release dump memory */
1072 dump_release(dumpsize);
1074 CYCLES_STATS_END(stacktrace_getClassContext)
1079 dump_release(dumpsize);
1081 CYCLES_STATS_END(stacktrace_getClassContext)
1087 /* stacktrace_getCurrentClass **************************************************
1089 Find the current class by walking the stack trace.
1091 Quote from the JNI documentation:
1093 In the Java 2 Platform, FindClass locates the class loader
1094 associated with the current native method. If the native code
1095 belongs to a system class, no class loader will be
1096 involved. Otherwise, the proper class loader will be invoked to
1097 load and link the named class. When FindClass is called through the
1098 Invocation Interface, there is no current native method or its
1099 associated class loader. In that case, the result of
1100 ClassLoader.getBaseClassLoader is used."
1102 *******************************************************************************/
1104 #if defined(ENABLE_JAVASE)
1105 classinfo *stacktrace_getCurrentClass(void)
1107 stacktracebuffer *stb;
1108 stacktrace_entry *ste;
1112 CYCLES_STATS_DECLARE_AND_START
1114 /* mark start of dump memory area */
1116 dumpsize = dump_size();
1118 /* create a stacktrace for the current thread */
1120 stb = stacktrace_create(THREADOBJECT);
1122 goto return_NULL; /* XXX exception: how to distinguish from normal NULL return? */
1124 /* iterate over all stacktrace entries and find the first suitable
1127 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1133 if (m->class == class_java_security_PrivilegedAction)
1136 if (m->class != NULL) {
1137 dump_release(dumpsize);
1139 CYCLES_STATS_END(stacktrace_getCurrentClass)
1145 /* no Java method found on the stack */
1148 dump_release(dumpsize);
1150 CYCLES_STATS_END(stacktrace_getCurrentClass)
1154 #endif /* ENABLE_JAVASE */
1157 /* stacktrace_getStack *********************************************************
1159 Create a 2-dimensional array for java.security.VMAccessControler.
1163 NULL if an exception has been thrown
1165 *******************************************************************************/
1167 java_objectarray *stacktrace_getStack(void)
1169 stacktracebuffer *stb;
1170 stacktrace_entry *ste;
1171 java_objectarray *oa;
1172 java_objectarray *classes;
1173 java_objectarray *methodnames;
1175 java_lang_String *str;
1178 CYCLES_STATS_DECLARE_AND_START
1180 /* mark start of dump memory area */
1182 dumpsize = dump_size();
1184 /* create a stacktrace for the current thread */
1186 stb = stacktrace_create(THREADOBJECT);
1190 /* get the first stacktrace entry */
1192 ste = &(stb->entries[0]);
1194 /* allocate all required arrays */
1196 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1201 classes = builtin_anewarray(stb->used, class_java_lang_Class);
1206 methodnames = builtin_anewarray(stb->used, class_java_lang_String);
1211 /* set up the 2-dimensional array */
1213 oa->data[0] = (java_objectheader *) classes;
1214 oa->data[1] = (java_objectheader *) methodnames;
1216 /* iterate over all stacktrace entries */
1218 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1219 c = ste->method->class;
1221 classes->data[i] = (java_objectheader *) c;
1222 str = javastring_new(ste->method->name);
1227 methodnames->data[i] = (java_objectheader *) str;
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)
1247 /* stacktrace_print_trace_from_buffer ******************************************
1249 Print the stacktrace of a given stacktracebuffer with CACAO intern
1250 methods (no Java help). This method is used by
1251 stacktrace_dump_trace and builtin_trace_exception.
1253 *******************************************************************************/
1255 void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
1257 stacktrace_entry *ste;
1261 ste = &(stb->entries[0]);
1263 for (i = 0; i < stb->used; i++, ste++) {
1267 utf_display_printable_ascii_classname(m->class->name);
1269 utf_display_printable_ascii(m->name);
1270 utf_display_printable_ascii(m->descriptor);
1272 if (m->flags & ACC_NATIVE) {
1273 puts("(Native Method)");
1277 utf_display_printable_ascii(m->class->sourcefile);
1278 printf(":%d)\n", (u4) ste->linenumber);
1282 /* just to be sure */
1288 /* stacktrace_dump_trace *******************************************************
1290 This method is call from signal_handler_sigusr1 to dump the
1291 stacktrace of the current thread to stdout.
1293 *******************************************************************************/
1295 void stacktrace_dump_trace(threadobject *thread)
1297 stacktracebuffer *stb;
1301 /* get methodinfo pointer from data segment */
1303 m = *((methodinfo **) (pv + MethodPointer));
1305 /* get current stackframe info pointer */
1307 psfi = STACKFRAMEINFO;
1309 /* fill new stackframe info structure */
1317 /* store new stackframe info pointer */
1322 /* mark start of dump memory area */
1324 dumpsize = dump_size();
1326 /* create a stacktrace for the current thread */
1328 stb = stacktrace_create(thread);
1330 /* print stacktrace */
1333 stacktrace_print_trace_from_buffer(stb);
1335 puts("\t<<No stacktrace available>>");
1339 dump_release(dumpsize);
1343 /* stacktrace_print_trace ******************************************************
1345 Print the stacktrace of a given exception. More or less a wrapper
1346 to stacktrace_print_trace_from_buffer.
1348 *******************************************************************************/
1350 void stacktrace_print_trace(java_objectheader *xptr)
1352 java_lang_Throwable *t;
1353 #if defined(WITH_CLASSPATH_GNU)
1354 java_lang_VMThrowable *vmt;
1356 stacktracecontainer *stc;
1357 stacktracebuffer *stb;
1359 t = (java_lang_Throwable *) xptr;
1364 /* now print the stacktrace */
1366 #if defined(WITH_CLASSPATH_GNU)
1368 stc = (stacktracecontainer *) vmt->vmData;
1370 #elif defined(WITH_CLASSPATH_CLDC1_1)
1371 stc = (stacktracecontainer *) t->backtrace;
1375 stacktrace_print_trace_from_buffer(stb);
1379 #if defined(ENABLE_CYCLES_STATS)
1380 void stacktrace_print_cycles_stats(FILE *file)
1382 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead,file);
1383 CYCLES_STATS_PRINT(stacktrace_fillInStackTrace,file);
1384 CYCLES_STATS_PRINT(stacktrace_getClassContext ,file);
1385 CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,file);
1386 CYCLES_STATS_PRINT(stacktrace_getStack ,file);
1392 * These are local overrides for various environment variables in Emacs.
1393 * Please do not remove this and leave it at the end of the file, where
1394 * Emacs will automagically detect them.
1395 * ---------------------------------------------------------------------
1398 * indent-tabs-mode: t
1402 * vim:noexpandtab:sw=4:ts=4: