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 7596 2007-03-28 21:05:53Z twisti $
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 GC
674 pointer to the stacktracebuffer, or
675 NULL if an exception has been thrown
677 *******************************************************************************/
679 stacktracebuffer *stacktrace_create(threadobject* thread)
681 stacktracebuffer *stb;
691 /* prevent compiler warnings */
697 /* create a stacktracebuffer in dump memory */
699 stb = DNEW(stacktracebuffer);
701 stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
703 stb->entries = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
705 /* The first element in the stackframe chain must always be a
706 native stackframeinfo (VMThrowable.fillInStackTrace is a native
709 /* We don't use the STACKFRAMEINFO macro here, as we have to use
710 the passed thread. */
712 #if defined(ENABLE_THREADS)
713 sfi = thread->_stackframeinfo;
715 sfi = _no_threads_stackframeinfo;
718 #define PRINTMETHODS 0
721 printf("\n\nfillInStackTrace start:\n");
725 /* Loop while we have a method pointer (asm_calljavafunction has
726 NULL) or there is a stackframeinfo in the chain. */
730 while ((m != NULL) || (sfi != NULL)) {
731 /* m == NULL should only happen for the first time and inline
732 stackframe infos, like from the exception stubs or the
736 /* for native stub stackframe infos, pv is always NULL */
738 if (sfi->pv == NULL) {
739 /* get methodinfo, sp and ra from the current stackframe info */
742 sp = sfi->sp; /* sp of parent Java function */
746 stacktrace_add_entry(stb, m, 0);
749 printf("ra=%p sp=%p, ", ra, sp);
751 printf(": native stub\n");
754 /* This is an native stub stackframe info, so we can
755 get the parent pv from the return address
758 #if defined(ENABLE_INTRP)
760 pv = codegen_get_pv_from_pc(ra);
764 #if defined(ENABLE_JIT)
765 pv = md_codegen_get_pv_from_pc(ra);
769 /* get methodinfo pointer from parent data segment */
771 code = *((codeinfo **) (pv + CodeinfoPointer));
773 /* For asm_vm_call_method the codeinfo pointer is
776 m = (code == NULL) ? NULL : code->m;
779 /* Inline stackframe infos are special: they have a
780 xpc of the actual exception position and the return
781 address saved since an inline stackframe info can
782 also be in a leaf method (no return address saved
783 on stack!!!). ATTENTION: This one is also for
784 hardware exceptions!!! */
786 /* get methodinfo, sp and ra from the current stackframe info */
788 m = sfi->method; /* m == NULL */
789 pv = sfi->pv; /* pv of parent Java function */
790 sp = sfi->sp; /* sp of parent Java function */
791 ra = sfi->ra; /* ra of parent Java function */
792 xpc = sfi->xpc; /* actual exception position */
795 printf("ra=%p sp=%p, ", ra, sp);
796 printf("NULL: inline stub\n");
800 /* get methodinfo from current Java method */
802 code = *((codeinfo **) (pv + CodeinfoPointer));
804 /* For asm_vm_call_method the codeinfo pointer is
807 m = (code == NULL) ? NULL : code->m;
809 /* if m == NULL, this is a asm_calljavafunction call */
813 printf("ra=%p sp=%p, ", ra, sp);
815 printf(": inline stub parent");
819 #if defined(ENABLE_INTRP)
823 /* add the method to the stacktrace */
825 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
827 /* get the current stack frame size */
829 framesize = *((u4 *) (pv + FrameSize));
832 printf(", framesize=%d\n", framesize);
836 /* Set stack pointer to stackframe of parent Java
837 function of the current Java function. */
839 #if defined(__I386__) || defined (__X86_64__)
840 sp += framesize + SIZEOF_VOID_P;
841 #elif defined(__SPARC_64__)
842 sp = md_get_framepointer(sp);
847 /* get data segment and methodinfo pointer from
850 #if defined(ENABLE_JIT)
851 pv = md_codegen_get_pv_from_pc(ra);
854 code = *((codeinfo **) (pv + CodeinfoPointer));
856 /* For asm_vm_call_method the codeinfo pointer is
859 m = (code == NULL) ? NULL : code->m;
861 #if defined(ENABLE_INTRP)
867 printf("ra=%p sp=%p, ", ra, sp);
868 printf("asm_calljavafunction\n");
874 /* get previous stackframeinfo in the chain */
880 printf("ra=%p sp=%p, ", ra, sp);
886 /* JIT method found, add it to the stacktrace (we subtract
887 1 from the return address since it points the the
888 instruction after call). */
890 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
892 /* get the current stack frame size */
894 framesize = *((u4 *) (pv + FrameSize));
897 printf(", framesize=%d\n", framesize);
901 /* get return address of current stack frame */
903 #if defined(ENABLE_JIT)
904 # if defined(ENABLE_INTRP)
906 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
909 ra = md_stacktrace_get_returnaddress(sp, framesize);
911 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
914 /* get data segment and methodinfo pointer from parent method */
916 #if defined(ENABLE_INTRP)
918 pv = codegen_get_pv_from_pc(ra);
922 #if defined(ENABLE_JIT)
923 # if defined(__SPARC_64__)
924 sp = md_get_framepointer(sp);
925 pv = md_get_pv_from_stackframe(sp);
927 pv = md_codegen_get_pv_from_pc(ra);
932 code = *((codeinfo **) (pv + CodeinfoPointer));
934 /* For asm_vm_call_method the codeinfo pointer is NULL. */
936 m = (code == NULL) ? NULL : code->m;
940 #if defined(ENABLE_INTRP)
942 sp = *(u1 **) (sp - framesize);
946 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
947 sp += framesize + SIZEOF_VOID_P;
948 #elif defined(__SPARC_64__)
949 /* already has the new sp */
957 /* return the stacktracebuffer */
963 /* stacktrace_fillInStackTrace *************************************************
965 Generate a stacktrace from the current thread for
966 java.lang.VMThrowable.fillInStackTrace.
968 *******************************************************************************/
970 stacktracecontainer *stacktrace_fillInStackTrace(void)
972 stacktracebuffer *stb;
973 stacktracecontainer *gcstc;
976 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
978 /* mark start of dump memory area */
980 dumpsize = dump_size();
982 /* create a stacktrace from the current thread */
984 stb = stacktrace_create(THREADOBJECT);
988 /* allocate memory from the GC heap and copy the stacktrace buffer */
989 /* ATTENTION: use stacktracecontainer for this and make it look like
992 gcstc_size = sizeof(stacktracebuffer) +
993 sizeof(stacktrace_entry) * stb->used;
994 gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
999 gcstc->stb.capacity = stb->capacity;
1000 gcstc->stb.used = stb->used;
1001 gcstc->stb.entries = gcstc->data;
1003 MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
1005 /* release dump memory */
1007 dump_release(dumpsize);
1009 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1010 stacktrace_overhead)
1014 dump_release(dumpsize);
1016 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
1017 stacktrace_overhead)
1023 /* stacktrace_getClassContext **************************************************
1025 Creates a Class context array.
1028 the array of java.lang.Class objects, or
1029 NULL if an exception has been thrown
1031 *******************************************************************************/
1033 java_objectarray *stacktrace_getClassContext(void)
1035 stacktracebuffer *stb;
1036 stacktrace_entry *ste;
1037 java_objectarray *oa;
1041 CYCLES_STATS_DECLARE_AND_START
1043 /* mark start of dump memory area */
1045 dumpsize = dump_size();
1047 /* create a stacktrace for the current thread */
1049 stb = stacktrace_create(THREADOBJECT);
1053 /* calculate the size of the Class array */
1055 for (i = 0, oalength = 0; i < stb->used; i++)
1056 if (stb->entries[i].method != NULL)
1059 /* The first entry corresponds to the method whose implementation */
1060 /* calls stacktrace_getClassContext. We remove that entry. */
1062 ste = &(stb->entries[0]);
1066 /* allocate the Class array */
1068 oa = builtin_anewarray(oalength, class_java_lang_Class);
1072 /* fill the Class array from the stacktracebuffer */
1074 for(i = 0; i < oalength; i++, ste++) {
1075 if (ste->method == NULL) {
1080 oa->data[i] = (java_objectheader *) ste->method->class;
1083 /* release dump memory */
1085 dump_release(dumpsize);
1087 CYCLES_STATS_END(stacktrace_getClassContext)
1092 dump_release(dumpsize);
1094 CYCLES_STATS_END(stacktrace_getClassContext)
1100 /* stacktrace_getCurrentClass **************************************************
1102 Find the current class by walking the stack trace.
1104 Quote from the JNI documentation:
1106 In the Java 2 Platform, FindClass locates the class loader
1107 associated with the current native method. If the native code
1108 belongs to a system class, no class loader will be
1109 involved. Otherwise, the proper class loader will be invoked to
1110 load and link the named class. When FindClass is called through the
1111 Invocation Interface, there is no current native method or its
1112 associated class loader. In that case, the result of
1113 ClassLoader.getBaseClassLoader is used."
1115 *******************************************************************************/
1117 #if defined(ENABLE_JAVASE)
1118 classinfo *stacktrace_getCurrentClass(void)
1120 stacktracebuffer *stb;
1121 stacktrace_entry *ste;
1125 CYCLES_STATS_DECLARE_AND_START
1127 /* mark start of dump memory area */
1129 dumpsize = dump_size();
1131 /* create a stacktrace for the current thread */
1133 stb = stacktrace_create(THREADOBJECT);
1135 goto return_NULL; /* XXX exception: how to distinguish from normal NULL return? */
1137 /* iterate over all stacktrace entries and find the first suitable
1140 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1146 if (m->class == class_java_security_PrivilegedAction)
1149 if (m->class != NULL) {
1150 dump_release(dumpsize);
1152 CYCLES_STATS_END(stacktrace_getCurrentClass)
1158 /* no Java method found on the stack */
1161 dump_release(dumpsize);
1163 CYCLES_STATS_END(stacktrace_getCurrentClass)
1167 #endif /* ENABLE_JAVASE */
1170 /* stacktrace_getStack *********************************************************
1172 Create a 2-dimensional array for java.security.VMAccessControler.
1176 NULL if an exception has been thrown
1178 *******************************************************************************/
1180 #if defined(ENABLE_JAVASE)
1181 java_objectarray *stacktrace_getStack(void)
1183 stacktracebuffer *stb;
1184 stacktrace_entry *ste;
1185 java_objectarray *oa;
1186 java_objectarray *classes;
1187 java_objectarray *methodnames;
1189 java_objectheader *string;
1192 CYCLES_STATS_DECLARE_AND_START
1194 /* mark start of dump memory area */
1196 dumpsize = dump_size();
1198 /* create a stacktrace for the current thread */
1200 stb = stacktrace_create(THREADOBJECT);
1205 /* get the first stacktrace entry */
1207 ste = &(stb->entries[0]);
1209 /* allocate all required arrays */
1211 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1216 classes = builtin_anewarray(stb->used, class_java_lang_Class);
1218 if (classes == NULL)
1221 methodnames = builtin_anewarray(stb->used, class_java_lang_String);
1223 if (methodnames == NULL)
1226 /* set up the 2-dimensional array */
1228 oa->data[0] = (java_objectheader *) classes;
1229 oa->data[1] = (java_objectheader *) methodnames;
1231 /* iterate over all stacktrace entries */
1233 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1234 c = ste->method->class;
1236 classes->data[i] = (java_objectheader *) c;
1238 string = javastring_new(ste->method->name);
1243 methodnames->data[i] = string;
1246 /* return the 2-dimensional array */
1248 dump_release(dumpsize);
1250 CYCLES_STATS_END(stacktrace_getStack)
1255 dump_release(dumpsize);
1257 CYCLES_STATS_END(stacktrace_getStack)
1261 #endif /* ENABLE_JAVASE */
1264 /* stacktrace_print_trace_from_buffer ******************************************
1266 Print the stacktrace of a given stacktracebuffer with CACAO intern
1267 methods (no Java help). This method is used by
1268 stacktrace_dump_trace and builtin_trace_exception.
1270 *******************************************************************************/
1272 void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
1274 stacktrace_entry *ste;
1278 ste = &(stb->entries[0]);
1280 for (i = 0; i < stb->used; i++, ste++) {
1284 utf_display_printable_ascii_classname(m->class->name);
1286 utf_display_printable_ascii(m->name);
1287 utf_display_printable_ascii(m->descriptor);
1289 if (m->flags & ACC_NATIVE) {
1290 puts("(Native Method)");
1294 utf_display_printable_ascii(m->class->sourcefile);
1295 printf(":%d)\n", (u4) ste->linenumber);
1299 /* just to be sure */
1305 /* stacktrace_dump_trace *******************************************************
1307 This method is call from signal_handler_sigusr1 to dump the
1308 stacktrace of the current thread to stdout.
1310 *******************************************************************************/
1312 void stacktrace_dump_trace(threadobject *thread)
1314 stacktracebuffer *stb;
1317 /* mark start of dump memory area */
1319 dumpsize = dump_size();
1321 /* create a stacktrace for the current thread */
1323 stb = stacktrace_create(thread);
1325 /* print stacktrace */
1328 stacktrace_print_trace_from_buffer(stb);
1330 puts("\t<<No stacktrace available>>");
1334 dump_release(dumpsize);
1338 /* stacktrace_print_trace ******************************************************
1340 Print the stacktrace of a given exception. More or less a wrapper
1341 to stacktrace_print_trace_from_buffer.
1343 *******************************************************************************/
1345 void stacktrace_print_trace(java_objectheader *xptr)
1347 java_lang_Throwable *t;
1348 #if defined(WITH_CLASSPATH_GNU)
1349 java_lang_VMThrowable *vmt;
1351 stacktracecontainer *stc;
1352 stacktracebuffer *stb;
1354 t = (java_lang_Throwable *) xptr;
1359 /* now print the stacktrace */
1361 #if defined(WITH_CLASSPATH_GNU)
1363 stc = (stacktracecontainer *) vmt->vmData;
1365 #elif defined(WITH_CLASSPATH_CLDC1_1)
1366 stc = (stacktracecontainer *) t->backtrace;
1370 stacktrace_print_trace_from_buffer(stb);
1374 #if defined(ENABLE_CYCLES_STATS)
1375 void stacktrace_print_cycles_stats(FILE *file)
1377 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead,file);
1378 CYCLES_STATS_PRINT(stacktrace_fillInStackTrace,file);
1379 CYCLES_STATS_PRINT(stacktrace_getClassContext ,file);
1380 CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,file);
1381 CYCLES_STATS_PRINT(stacktrace_getStack ,file);
1387 * These are local overrides for various environment variables in Emacs.
1388 * Please do not remove this and leave it at the end of the file, where
1389 * Emacs will automagically detect them.
1390 * ---------------------------------------------------------------------
1393 * indent-tabs-mode: t
1397 * vim:noexpandtab:sw=4:ts=4: