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 7632 2007-04-02 20:05:05Z michi $
38 #include "mm/gc-common.h"
39 #include "mm/memory.h"
41 #include "vm/jit/stacktrace.h"
43 #include "vm/global.h" /* required here for native includes */
44 #include "native/jni.h"
45 #include "native/include/java_lang_Throwable.h"
47 #if defined(WITH_CLASSPATH_GNU)
48 # include "native/include/java_lang_VMThrowable.h"
51 #if defined(ENABLE_THREADS)
52 # include "threads/native/threads.h"
54 # include "threads/none/threads.h"
57 #include "toolbox/logging.h"
59 #include "vm/builtin.h"
60 #include "vm/cycles-stats.h"
61 #include "vm/exceptions.h"
62 #include "vm/stringlocal.h"
65 #include "vm/jit/asmpart.h"
66 #include "vm/jit/codegen-common.h"
67 #include "vm/jit/methodheader.h"
69 #include "vmcore/class.h"
70 #include "vmcore/loader.h"
71 #include "vmcore/options.h"
74 /* global variables ***********************************************************/
75 #if !defined(ENABLE_THREADS)
76 stackframeinfo *_no_threads_stackframeinfo = NULL;
79 CYCLES_STATS_DECLARE(stacktrace_overhead ,100,1)
80 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace,40,5000)
81 CYCLES_STATS_DECLARE(stacktrace_getClassContext ,40,5000)
82 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass ,40,5000)
83 CYCLES_STATS_DECLARE(stacktrace_getStack ,40,10000)
86 /* stacktrace_create_stackframeinfo ********************************************
88 Creates an stackframe info structure for inline code in the
91 *******************************************************************************/
93 #if defined(ENABLE_INTRP)
94 void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
97 stackframeinfo **psfi;
101 /* get current stackframe info pointer */
103 psfi = STACKFRAMEINFO;
105 /* if we don't have pv handy */
108 #if defined(ENABLE_INTRP)
110 pv = codegen_get_pv_from_pc(ra);
114 #if defined(ENABLE_JIT)
115 pv = md_codegen_get_pv_from_pc(ra);
120 /* get codeinfo pointer from data segment */
122 code = *((codeinfo **) (pv + CodeinfoPointer));
124 /* For asm_vm_call_method the codeinfo pointer is NULL. */
126 m = (code == NULL) ? NULL : code->m;
128 /* fill new stackframe info structure */
136 /* xpc is the same as ra, but is required in stacktrace_create */
140 /* store new stackframe info pointer */
144 #endif /* defined(ENABLE_INTRP) */
147 /* stacktrace_create_inline_stackframeinfo *************************************
149 Creates an stackframe info structure for an inline exception stub.
151 *******************************************************************************/
153 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
154 u1 *sp, u1 *ra, u1 *xpc)
156 stackframeinfo **psfi;
158 /* get current stackframe info pointer */
160 psfi = STACKFRAMEINFO;
162 #if defined(ENABLE_INTRP)
164 /* if we don't have pv handy */
167 pv = codegen_get_pv_from_pc(ra);
172 /* fill new stackframe info structure */
181 /* store new stackframe info pointer */
187 /* stacktrace_create_extern_stackframeinfo *************************************
189 Creates an stackframe info structure for an extern exception
190 (hardware or assembler).
192 *******************************************************************************/
194 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
195 u1 *sp, u1 *ra, u1 *xpc)
197 stackframeinfo **psfi;
198 #if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__)
201 #if defined(ENABLE_JIT)
205 /* get current stackframe info pointer */
207 psfi = STACKFRAMEINFO;
209 /* sometimes we don't have pv handy (e.g. in asmpart.S:
210 L_asm_call_jit_compiler_exception or in the interpreter). */
213 #if defined(ENABLE_INTRP)
215 pv = codegen_get_pv_from_pc(ra);
219 #if defined(ENABLE_JIT)
220 # if defined(__SPARC_64__)
221 pv = md_get_pv_from_stackframe(sp);
223 pv = md_codegen_get_pv_from_pc(ra);
229 #if defined(ENABLE_JIT)
230 # if defined(ENABLE_INTRP)
231 /* When using the interpreter, we pass RA to the function. */
235 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
236 /* On i386 and x86_64 we always have to get the return address
238 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
239 the RA from stack. */
241 framesize = *((u4 *) (pv + FrameSize));
243 ra = md_stacktrace_get_returnaddress(sp, framesize);
245 /* If the method is a non-leaf function, we need to get the return
246 address from the stack. For leaf functions the return address
247 is set correctly. This makes the assembler and the signal
248 handler code simpler. */
250 isleafmethod = *((s4 *) (pv + IsLeaf));
253 framesize = *((u4 *) (pv + FrameSize));
255 ra = md_stacktrace_get_returnaddress(sp, framesize);
258 # if defined(ENABLE_INTRP)
261 #endif /* defined(ENABLE_JIT) */
263 /* fill new stackframe info structure */
272 /* store new stackframe info pointer */
278 /* stacktrace_create_native_stackframeinfo *************************************
280 Creates a stackframe info structure for a native stub.
282 *******************************************************************************/
284 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
287 stackframeinfo **psfi;
291 /* get codeinfo pointer from data segment */
293 code = *((codeinfo **) (pv + CodeinfoPointer));
295 /* For asm_vm_call_method the codeinfo pointer is NULL. */
297 m = (code == NULL) ? NULL : code->m;
299 /* get current stackframe info pointer */
301 psfi = STACKFRAMEINFO;
303 /* fill new stackframe info structure */
312 /* store new stackframe info pointer */
318 /* stacktrace_remove_stackframeinfo ********************************************
320 Remove the topmost stackframeinfo in the current thread.
322 *******************************************************************************/
324 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
326 stackframeinfo **psfi;
328 /* get current stackframe info pointer */
330 psfi = STACKFRAMEINFO;
332 /* restore the old pointer */
338 /* stacktrace_inline_arithmeticexception ***************************************
340 Creates an ArithemticException for inline stub.
342 *******************************************************************************/
344 java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
348 java_objectheader *o;
350 /* create stackframeinfo */
352 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
354 /* create exception */
356 o = exceptions_new_arithmeticexception();
358 /* remove stackframeinfo */
360 stacktrace_remove_stackframeinfo(&sfi);
366 /* stacktrace_inline_arrayindexoutofboundsexception ****************************
368 Creates an ArrayIndexOutOfBoundsException for inline stub.
370 *******************************************************************************/
372 java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
379 java_objectheader *o;
381 /* create stackframeinfo */
383 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
385 /* create exception */
387 o = exceptions_new_arrayindexoutofboundsexception(index);
389 /* remove stackframeinfo */
391 stacktrace_remove_stackframeinfo(&sfi);
397 /* stacktrace_inline_arraystoreexception ***************************************
399 Creates an ArrayStoreException for inline stub.
401 *******************************************************************************/
403 java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
407 java_objectheader *o;
409 /* create stackframeinfo */
411 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
413 /* create exception */
415 o = exceptions_new_arraystoreexception();
417 /* remove stackframeinfo */
419 stacktrace_remove_stackframeinfo(&sfi);
425 /* stacktrace_inline_classcastexception ****************************************
427 Creates an ClassCastException for inline stub.
429 *******************************************************************************/
431 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
433 java_objectheader *o)
436 java_objectheader *e;
438 /* create stackframeinfo */
440 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
442 /* create exception */
444 e = exceptions_new_classcastexception(o);
446 /* remove stackframeinfo */
448 stacktrace_remove_stackframeinfo(&sfi);
454 /* stacktrace_inline_nullpointerexception **************************************
456 Creates an NullPointerException for inline stub.
458 *******************************************************************************/
460 java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
464 java_objectheader *o;
466 /* create stackframeinfo */
468 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
470 /* create exception */
472 o = exceptions_new_nullpointerexception();
474 /* remove stackframeinfo */
476 stacktrace_remove_stackframeinfo(&sfi);
482 /* stacktrace_inline_fillInStackTrace ******************************************
484 Fills in the correct stacktrace into an existing exception object
485 (this one is for inline exception stubs).
487 *******************************************************************************/
489 java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
493 java_objectheader *o;
496 /* create stackframeinfo */
498 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
505 /* clear exception */
507 *exceptionptr = NULL;
509 /* resolve methodinfo pointer from exception object */
511 #if defined(ENABLE_JAVASE)
512 m = class_resolvemethod(o->vftbl->class,
513 utf_fillInStackTrace,
514 utf_void__java_lang_Throwable);
515 #elif defined(ENABLE_JAVAME_CLDC1_1)
516 m = class_resolvemethod(o->vftbl->class,
517 utf_fillInStackTrace,
525 (void) vm_call_method(m, o);
527 /* remove stackframeinfo */
529 stacktrace_remove_stackframeinfo(&sfi);
535 /* stacktrace_hardware_arithmeticexception *************************************
537 Creates an ArithemticException for inline stub.
539 *******************************************************************************/
541 java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
545 java_objectheader *o;
547 /* create stackframeinfo */
549 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
551 /* create exception */
553 o = exceptions_new_arithmeticexception();
555 /* remove stackframeinfo */
557 stacktrace_remove_stackframeinfo(&sfi);
563 /* stacktrace_hardware_nullpointerexception ************************************
565 Creates an NullPointerException for the SIGSEGV signal handler.
567 *******************************************************************************/
569 java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
573 java_objectheader *o;
575 /* create stackframeinfo */
577 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
579 /* create exception */
581 o = exceptions_new_nullpointerexception();
583 /* remove stackframeinfo */
585 stacktrace_remove_stackframeinfo(&sfi);
591 /* stacktrace_add_entry ********************************************************
593 Adds a new entry to the stacktrace buffer.
595 *******************************************************************************/
597 static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
599 stacktrace_entry *ste;
601 /* check if we already reached the buffer capacity */
603 if (stb->used >= stb->capacity) {
604 /* reallocate new memory */
606 stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
607 stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
609 /* set new buffer capacity */
611 stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
614 /* insert the current entry */
616 ste = &(stb->entries[stb->used]);
619 ste->linenumber = line;
621 /* increase entries used count */
627 /* stacktrace_add_method *******************************************************
629 Add stacktrace entries[1] for the given method to the stacktrace buffer.
632 stb.........stacktracebuffer to fill
633 m...........method for which entries should be created
634 pv..........pv of method
635 pc..........position of program counter within the method's code
638 true, if stacktrace entries were successfully created, false otherwise.
640 [1] In case of inlined methods there may be more than one stacktrace
641 entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
643 *******************************************************************************/
645 static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
648 codeinfo *code; /* compiled realization of method */
651 /* find the realization of the method the pc is in */
653 code = *((codeinfo **) (pv + CodeinfoPointer));
655 /* search the line number table */
657 linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
659 /* now add a new entry to the staktrace */
661 stacktrace_add_entry(stb, m, linenumber);
667 /* stacktrace_create ***********************************************************
669 Generates a stacktrace from the thread passed into a
670 stacktracebuffer. The stacktracebuffer is allocated on the
674 pointer to the stacktracebuffer, or
675 NULL if there is no stacktrace available for the
678 *******************************************************************************/
680 stacktracebuffer *stacktrace_create(threadobject* thread)
682 stacktracebuffer *stb;
692 /* prevent compiler warnings */
698 /* create a stacktracebuffer in dump memory */
700 stb = DNEW(stacktracebuffer);
702 stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
704 stb->entries = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
706 /* The first element in the stackframe chain must always be a
707 native stackframeinfo (VMThrowable.fillInStackTrace is a native
710 /* We don't use the STACKFRAMEINFO macro here, as we have to use
711 the passed thread. */
713 #if defined(ENABLE_THREADS)
714 sfi = thread->_stackframeinfo;
716 sfi = _no_threads_stackframeinfo;
719 #define PRINTMETHODS 0
722 printf("\n\nfillInStackTrace start:\n");
726 /* Loop while we have a method pointer (asm_calljavafunction has
727 NULL) or there is a stackframeinfo in the chain. */
731 while ((m != NULL) || (sfi != NULL)) {
732 /* m == NULL should only happen for the first time and inline
733 stackframe infos, like from the exception stubs or the
737 /* for native stub stackframe infos, pv is always NULL */
739 if (sfi->pv == NULL) {
740 /* get methodinfo, sp and ra from the current stackframe info */
743 sp = sfi->sp; /* sp of parent Java function */
747 stacktrace_add_entry(stb, m, 0);
750 printf("ra=%p sp=%p, ", ra, sp);
752 printf(": native stub\n");
755 /* This is an native stub stackframe info, so we can
756 get the parent pv from the return address
759 #if defined(ENABLE_INTRP)
761 pv = codegen_get_pv_from_pc(ra);
765 #if defined(ENABLE_JIT)
766 pv = md_codegen_get_pv_from_pc(ra);
770 /* get methodinfo pointer from parent data segment */
772 code = *((codeinfo **) (pv + CodeinfoPointer));
774 /* For asm_vm_call_method the codeinfo pointer is
777 m = (code == NULL) ? NULL : code->m;
780 /* Inline stackframe infos are special: they have a
781 xpc of the actual exception position and the return
782 address saved since an inline stackframe info can
783 also be in a leaf method (no return address saved
784 on stack!!!). ATTENTION: This one is also for
785 hardware exceptions!!! */
787 /* get methodinfo, sp and ra from the current stackframe info */
789 m = sfi->method; /* m == NULL */
790 pv = sfi->pv; /* pv of parent Java function */
791 sp = sfi->sp; /* sp of parent Java function */
792 ra = sfi->ra; /* ra of parent Java function */
793 xpc = sfi->xpc; /* actual exception position */
796 printf("ra=%p sp=%p, ", ra, sp);
797 printf("NULL: inline stub\n");
801 /* get methodinfo from current Java method */
803 code = *((codeinfo **) (pv + CodeinfoPointer));
805 /* For asm_vm_call_method the codeinfo pointer is
808 m = (code == NULL) ? NULL : code->m;
810 /* if m == NULL, this is a asm_calljavafunction call */
814 printf("ra=%p sp=%p, ", ra, sp);
816 printf(": inline stub parent");
820 #if defined(ENABLE_INTRP)
824 /* add the method to the stacktrace */
826 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
828 /* get the current stack frame size */
830 framesize = *((u4 *) (pv + FrameSize));
833 printf(", framesize=%d\n", framesize);
837 /* Set stack pointer to stackframe of parent Java
838 function of the current Java function. */
840 #if defined(__I386__) || defined (__X86_64__)
841 sp += framesize + SIZEOF_VOID_P;
842 #elif defined(__SPARC_64__)
843 sp = md_get_framepointer(sp);
848 /* get data segment and methodinfo pointer from
851 #if defined(ENABLE_JIT)
852 pv = md_codegen_get_pv_from_pc(ra);
855 code = *((codeinfo **) (pv + CodeinfoPointer));
857 /* For asm_vm_call_method the codeinfo pointer is
860 m = (code == NULL) ? NULL : code->m;
862 #if defined(ENABLE_INTRP)
868 printf("ra=%p sp=%p, ", ra, sp);
869 printf("asm_calljavafunction\n");
875 /* get previous stackframeinfo in the chain */
881 printf("ra=%p sp=%p, ", ra, sp);
887 /* JIT method found, add it to the stacktrace (we subtract
888 1 from the return address since it points the the
889 instruction after call). */
891 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
893 /* get the current stack frame size */
895 framesize = *((u4 *) (pv + FrameSize));
898 printf(", framesize=%d\n", framesize);
902 /* get return address of current stack frame */
904 #if defined(ENABLE_JIT)
905 # if defined(ENABLE_INTRP)
907 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
910 ra = md_stacktrace_get_returnaddress(sp, framesize);
912 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
915 /* get data segment and methodinfo pointer from parent method */
917 #if defined(ENABLE_INTRP)
919 pv = codegen_get_pv_from_pc(ra);
923 #if defined(ENABLE_JIT)
924 # if defined(__SPARC_64__)
925 sp = md_get_framepointer(sp);
926 pv = md_get_pv_from_stackframe(sp);
928 pv = md_codegen_get_pv_from_pc(ra);
933 code = *((codeinfo **) (pv + CodeinfoPointer));
935 /* For asm_vm_call_method the codeinfo pointer is NULL. */
937 m = (code == NULL) ? NULL : code->m;
941 #if defined(ENABLE_INTRP)
943 sp = *(u1 **) (sp - framesize);
947 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
948 sp += framesize + SIZEOF_VOID_P;
949 #elif defined(__SPARC_64__)
950 /* already has the new sp */
958 /* return the stacktracebuffer */
967 /* stacktrace_fillInStackTrace *************************************************
969 Generate a stacktrace from the current thread for
970 java.lang.VMThrowable.fillInStackTrace.
972 *******************************************************************************/
974 stacktracecontainer *stacktrace_fillInStackTrace(void)
976 stacktracebuffer *stb;
977 stacktracecontainer *gcstc;
980 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
982 /* mark start of dump memory area */
984 dumpsize = dump_size();
986 /* create a stacktrace from the current thread */
988 stb = stacktrace_create(THREADOBJECT);
992 /* allocate memory from the GC heap and copy the stacktrace buffer */
993 /* ATTENTION: use stacktracecontainer for this and make it look like
996 gcstc_size = sizeof(stacktracebuffer) +
997 sizeof(stacktrace_entry) * stb->used;
998 gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
1003 gcstc->stb.capacity = stb->capacity;
1004 gcstc->stb.used = stb->used;
1005 gcstc->stb.entries = gcstc->data;
1007 MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
1009 /* release dump memory */
1011 dump_release(dumpsize);
1013 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1014 stacktrace_overhead)
1018 dump_release(dumpsize);
1020 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1021 stacktrace_overhead)
1027 /* stacktrace_getClassContext **************************************************
1029 Creates a Class context array.
1032 the array of java.lang.Class objects, or
1033 NULL if an exception has been thrown
1035 *******************************************************************************/
1037 java_objectarray *stacktrace_getClassContext(void)
1039 stacktracebuffer *stb;
1040 stacktrace_entry *ste;
1041 java_objectarray *oa;
1045 CYCLES_STATS_DECLARE_AND_START
1047 /* mark start of dump memory area */
1049 dumpsize = dump_size();
1051 /* create a stacktrace for the current thread */
1053 stb = stacktrace_create(THREADOBJECT);
1057 /* calculate the size of the Class array */
1059 for (i = 0, oalength = 0; i < stb->used; i++)
1060 if (stb->entries[i].method != NULL)
1063 /* The first entry corresponds to the method whose implementation */
1064 /* calls stacktrace_getClassContext. We remove that entry. */
1066 ste = &(stb->entries[0]);
1070 /* allocate the Class array */
1072 oa = builtin_anewarray(oalength, class_java_lang_Class);
1076 /* fill the Class array from the stacktracebuffer */
1078 for(i = 0; i < oalength; i++, ste++) {
1079 if (ste->method == NULL) {
1084 oa->data[i] = (java_objectheader *) ste->method->class;
1087 /* release dump memory */
1089 dump_release(dumpsize);
1091 CYCLES_STATS_END(stacktrace_getClassContext)
1096 dump_release(dumpsize);
1098 CYCLES_STATS_END(stacktrace_getClassContext)
1104 /* stacktrace_getCurrentClass **************************************************
1106 Find the current class by walking the stack trace.
1108 Quote from the JNI documentation:
1110 In the Java 2 Platform, FindClass locates the class loader
1111 associated with the current native method. If the native code
1112 belongs to a system class, no class loader will be
1113 involved. Otherwise, the proper class loader will be invoked to
1114 load and link the named class. When FindClass is called through the
1115 Invocation Interface, there is no current native method or its
1116 associated class loader. In that case, the result of
1117 ClassLoader.getBaseClassLoader is used."
1119 *******************************************************************************/
1121 #if defined(ENABLE_JAVASE)
1122 classinfo *stacktrace_getCurrentClass(void)
1124 stacktracebuffer *stb;
1125 stacktrace_entry *ste;
1129 CYCLES_STATS_DECLARE_AND_START
1131 /* mark start of dump memory area */
1133 dumpsize = dump_size();
1135 /* create a stacktrace for the current thread */
1137 stb = stacktrace_create(THREADOBJECT);
1139 goto return_NULL; /* XXX exception: how to distinguish from normal NULL return? */
1141 /* iterate over all stacktrace entries and find the first suitable
1144 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1150 if (m->class == class_java_security_PrivilegedAction)
1153 if (m->class != NULL) {
1154 dump_release(dumpsize);
1156 CYCLES_STATS_END(stacktrace_getCurrentClass)
1162 /* no Java method found on the stack */
1165 dump_release(dumpsize);
1167 CYCLES_STATS_END(stacktrace_getCurrentClass)
1171 #endif /* ENABLE_JAVASE */
1174 /* stacktrace_getStack *********************************************************
1176 Create a 2-dimensional array for java.security.VMAccessControler.
1180 NULL if an exception has been thrown
1182 *******************************************************************************/
1184 #if defined(ENABLE_JAVASE)
1185 java_objectarray *stacktrace_getStack(void)
1187 stacktracebuffer *stb;
1188 stacktrace_entry *ste;
1189 java_objectarray *oa;
1190 java_objectarray *classes;
1191 java_objectarray *methodnames;
1193 java_objectheader *string;
1196 CYCLES_STATS_DECLARE_AND_START
1198 /* mark start of dump memory area */
1200 dumpsize = dump_size();
1202 /* create a stacktrace for the current thread */
1204 stb = stacktrace_create(THREADOBJECT);
1209 /* get the first stacktrace entry */
1211 ste = &(stb->entries[0]);
1213 /* allocate all required arrays */
1215 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1220 classes = builtin_anewarray(stb->used, class_java_lang_Class);
1222 if (classes == NULL)
1225 methodnames = builtin_anewarray(stb->used, class_java_lang_String);
1227 if (methodnames == NULL)
1230 /* set up the 2-dimensional array */
1232 oa->data[0] = (java_objectheader *) classes;
1233 oa->data[1] = (java_objectheader *) methodnames;
1235 /* iterate over all stacktrace entries */
1237 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1238 c = ste->method->class;
1240 classes->data[i] = (java_objectheader *) c;
1242 string = javastring_new(ste->method->name);
1247 methodnames->data[i] = string;
1250 /* return the 2-dimensional array */
1252 dump_release(dumpsize);
1254 CYCLES_STATS_END(stacktrace_getStack)
1259 dump_release(dumpsize);
1261 CYCLES_STATS_END(stacktrace_getStack)
1265 #endif /* ENABLE_JAVASE */
1268 /* stacktrace_print_trace_from_buffer ******************************************
1270 Print the stacktrace of a given stacktracebuffer with CACAO intern
1271 methods (no Java help). This method is used by
1272 stacktrace_dump_trace and builtin_trace_exception.
1274 *******************************************************************************/
1276 void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
1278 stacktrace_entry *ste;
1282 ste = &(stb->entries[0]);
1284 for (i = 0; i < stb->used; i++, ste++) {
1288 utf_display_printable_ascii_classname(m->class->name);
1290 utf_display_printable_ascii(m->name);
1291 utf_display_printable_ascii(m->descriptor);
1293 if (m->flags & ACC_NATIVE) {
1294 puts("(Native Method)");
1298 utf_display_printable_ascii(m->class->sourcefile);
1299 printf(":%d)\n", (u4) ste->linenumber);
1303 /* just to be sure */
1309 /* stacktrace_dump_trace *******************************************************
1311 This method is call from signal_handler_sigusr1 to dump the
1312 stacktrace of the current thread to stdout.
1314 *******************************************************************************/
1316 void stacktrace_dump_trace(threadobject *thread)
1318 stacktracebuffer *stb;
1321 /* mark start of dump memory area */
1323 dumpsize = dump_size();
1325 /* create a stacktrace for the current thread */
1327 stb = stacktrace_create(thread);
1329 /* print stacktrace */
1332 stacktrace_print_trace_from_buffer(stb);
1334 puts("\t<<No stacktrace available>>");
1338 dump_release(dumpsize);
1342 /* stacktrace_print_trace ******************************************************
1344 Print the stacktrace of a given exception. More or less a wrapper
1345 to stacktrace_print_trace_from_buffer.
1347 *******************************************************************************/
1349 void stacktrace_print_trace(java_objectheader *xptr)
1351 java_lang_Throwable *t;
1352 #if defined(WITH_CLASSPATH_GNU)
1353 java_lang_VMThrowable *vmt;
1355 stacktracecontainer *stc;
1356 stacktracebuffer *stb;
1358 t = (java_lang_Throwable *) xptr;
1363 /* now print the stacktrace */
1365 #if defined(WITH_CLASSPATH_GNU)
1367 stc = (stacktracecontainer *) vmt->vmData;
1369 #elif defined(WITH_CLASSPATH_CLDC1_1)
1370 stc = (stacktracecontainer *) t->backtrace;
1374 stacktrace_print_trace_from_buffer(stb);
1378 #if defined(ENABLE_CYCLES_STATS)
1379 void stacktrace_print_cycles_stats(FILE *file)
1381 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead,file);
1382 CYCLES_STATS_PRINT(stacktrace_fillInStackTrace,file);
1383 CYCLES_STATS_PRINT(stacktrace_getClassContext ,file);
1384 CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,file);
1385 CYCLES_STATS_PRINT(stacktrace_getStack ,file);
1391 * These are local overrides for various environment variables in Emacs.
1392 * Please do not remove this and leave it at the end of the file, where
1393 * Emacs will automagically detect them.
1394 * ---------------------------------------------------------------------
1397 * indent-tabs-mode: t
1401 * vim:noexpandtab:sw=4:ts=4: