1 /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
38 #include "mm/memory.hpp"
40 #include "vm/jit/stacktrace.hpp"
42 #include "native/llni.h"
44 #include "threads/thread.hpp"
46 #include "toolbox/logging.hpp"
48 #include "vm/array.hpp"
49 #include "vm/jit/builtin.hpp"
50 #include "vm/class.hpp"
51 #include "vm/cycles-stats.h"
52 #include "vm/exceptions.hpp"
53 #include "vm/globals.hpp"
54 #include "vm/javaobjects.hpp"
55 #include "vm/loader.hpp"
56 #include "vm/method.hpp"
57 #include "vm/options.h"
58 #include "vm/string.hpp"
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/codegen-common.hpp"
63 #include "vm/jit/linenumbertable.hpp"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/methodtree.h"
68 // FIXME Use C-linkage for now.
71 /* global variables ***********************************************************/
73 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
74 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
75 CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
76 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
77 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
78 CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
81 /* stacktrace_stackframeinfo_add ***********************************************
83 Fills a stackframe info structure with the given or calculated
84 values and adds it to the chain.
86 *******************************************************************************/
88 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
90 stackframeinfo_t *currentsfi;
92 #if defined(ENABLE_JIT)
96 /* Get current stackframe info. */
98 currentsfi = threads_get_current_stackframeinfo();
100 /* sometimes we don't have pv handy (e.g. in asmpart.S:
101 L_asm_call_jit_compiler_exception or in the interpreter). */
104 #if defined(ENABLE_INTRP)
106 pv = methodtree_find(ra);
110 #if defined(ENABLE_JIT)
111 # if defined(__SPARC_64__)
112 pv = md_get_pv_from_stackframe(sp);
114 pv = md_codegen_get_pv_from_pc(ra);
120 /* Get codeinfo pointer for the parent Java method. */
122 code = code_get_codeinfo_for_pv(pv);
125 /* assert(m != NULL); */
127 #if defined(ENABLE_JIT)
128 # if defined(ENABLE_INTRP)
129 /* When using the interpreter, we pass RA to the function. */
133 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
134 /* On i386 and x86_64 we always have to get the return address
136 /* m68k has return address on stack always */
137 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
138 the RA from stack. */
140 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
142 ra = md_stacktrace_get_returnaddress(sp, framesize);
144 /* If the method is a non-leaf function, we need to get the
145 return address from the stack. For leaf functions the
146 return address is set correctly. This makes the assembler
147 and the signal handler code simpler. The code is NULL is
148 the asm_vm_call_method special case. */
150 if ((code == NULL) || !code_is_leafmethod(code)) {
151 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
153 ra = md_stacktrace_get_returnaddress(sp, framesize);
156 # if defined(ENABLE_INTRP)
161 /* Calculate XPC when not given. The XPC is then the return
162 address of the current method minus 1 because the RA points to
163 the instruction after the call instruction. This is required
164 e.g. for method stubs. */
167 xpc = (void *) (((intptr_t) ra) - 1);
170 /* Fill new stackframeinfo structure. */
172 sfi->prev = currentsfi;
180 if (opt_DebugStackFrameInfo) {
182 log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
183 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
184 method_print(sfi->code->m);
190 /* Store new stackframeinfo pointer. */
192 threads_set_current_stackframeinfo(sfi);
194 /* set the native world flag for the current thread */
195 /* ATTENTION: This flag tells the GC how to treat this thread in case of
196 a collection. Set this flag _after_ a valid stackframe info was set. */
198 THREAD_NATIVEWORLD_ENTER;
202 /* stacktrace_stackframeinfo_remove ********************************************
204 Remove the given stackframeinfo from the chain in the current
207 *******************************************************************************/
209 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
211 /* Clear the native world flag for the current thread. */
212 /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
214 THREAD_NATIVEWORLD_EXIT;
217 if (opt_DebugStackFrameInfo) {
219 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
220 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
221 method_print(sfi->code->m);
227 /* Set previous stackframe info. */
229 threads_set_current_stackframeinfo(sfi->prev);
233 /* stacktrace_stackframeinfo_fill **********************************************
235 Fill the temporary stackframeinfo structure with the values given
239 tmpsfi ... temporary stackframeinfo
240 sfi ...... stackframeinfo to be used in the next iteration
242 *******************************************************************************/
244 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
248 assert(tmpsfi != NULL);
251 /* Fill the temporary stackframeinfo. */
253 tmpsfi->code = sfi->code;
254 tmpsfi->pv = sfi->pv;
255 tmpsfi->sp = sfi->sp;
256 tmpsfi->ra = sfi->ra;
257 tmpsfi->xpc = sfi->xpc;
259 /* Set the previous stackframe info of the temporary one to the
260 next in the chain. */
262 tmpsfi->prev = sfi->prev;
265 if (opt_DebugStackTrace)
266 log_println("[stacktrace fill]");
271 /* stacktrace_stackframeinfo_next **********************************************
273 Walk the stack (or the stackframeinfo-chain) to the next method and
274 return the new stackframe values in the temporary stackframeinfo
277 ATTENTION: This function does NOT skip builtin methods!
280 tmpsfi ... temporary stackframeinfo of current method
282 *******************************************************************************/
284 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
292 stackframeinfo_t *prevsfi;
296 assert(tmpsfi != NULL);
298 /* Get values from the stackframeinfo. */
306 /* Get the current stack frame size. */
308 framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
310 /* Get the RA of the current stack frame (RA to the parent Java
311 method) if the current method is a non-leaf method. Otherwise
312 the value in the stackframeinfo is correct (from the signal
315 #if defined(ENABLE_JIT)
316 # if defined(ENABLE_INTRP)
318 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
322 if (!code_is_leafmethod(code))
323 ra = md_stacktrace_get_returnaddress(sp, framesize);
326 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
329 /* Get the PV for the parent Java method. */
331 #if defined(ENABLE_INTRP)
333 pv = methodtree_find(ra);
337 #if defined(ENABLE_JIT)
338 # if defined(__SPARC_64__)
339 sp = md_get_framepointer(sp);
340 pv = md_get_pv_from_stackframe(sp);
342 pv = md_codegen_get_pv_from_pc(ra);
347 /* Get the codeinfo pointer for the parent Java method. */
349 code = code_get_codeinfo_for_pv(pv);
351 /* Calculate the SP for the parent Java method. */
353 #if defined(ENABLE_INTRP)
355 sp = *(u1 **) (sp - framesize);
359 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
360 sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
361 #elif defined(__SPARC_64__)
362 /* already has the new sp */
364 sp = (void *) (((intptr_t) sp) + framesize);
368 /* If the new codeinfo pointer is NULL we reached a
369 asm_vm_call_method function. In this case we get the next
370 values from the previous stackframeinfo in the chain.
371 Otherwise the new values have been calculated before. */
374 prevsfi = tmpsfi->prev;
376 /* If the previous stackframeinfo in the chain is NULL we
377 reached the top of the stacktrace. We set code and prev to
378 NULL to mark the end, which is checked in
379 stacktrace_stackframeinfo_end_check. */
381 if (prevsfi == NULL) {
387 /* Fill the temporary stackframeinfo with the new values. */
389 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
392 /* Store the new values in the stackframeinfo. NOTE: We
393 subtract 1 from the RA to get the XPC, because the RA
394 points to the instruction after the call instruction. */
400 tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
404 /* Print current method information. */
406 if (opt_DebugStackTrace) {
408 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
409 tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
411 method_print(tmpsfi->code->m);
419 /* stacktrace_stackframeinfo_end_check *****************************************
421 Check if we reached the end of the stacktrace.
424 tmpsfi ... temporary stackframeinfo of current method
427 true .... the end is reached
428 false ... the end is not reached
430 *******************************************************************************/
432 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
436 assert(tmpsfi != NULL);
438 if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
440 if (opt_DebugStackTrace)
441 log_println("[stacktrace stop]");
451 /* stacktrace_depth ************************************************************
453 Calculates and returns the depth of the current stacktrace.
456 sfi ... stackframeinfo where to start the stacktrace
459 depth of the stacktrace
461 *******************************************************************************/
463 static int stacktrace_depth(stackframeinfo_t *sfi)
465 stackframeinfo_t tmpsfi;
470 if (opt_DebugStackTrace)
471 log_println("[stacktrace_depth]");
474 /* XXX This is not correct, but a workaround for threads-dump for
476 /* assert(sfi != NULL); */
480 /* Iterate over all stackframes. */
484 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
485 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
486 stacktrace_stackframeinfo_next(&tmpsfi)) {
487 /* Get methodinfo. */
491 /* Skip builtin methods. */
493 if (m->flags & ACC_METHOD_BUILTIN)
503 /* stacktrace_get **************************************************************
505 Builds and returns a stacktrace starting from the given stackframe
506 info and returns the stacktrace structure wrapped in a Java
507 byte-array to not confuse the GC.
510 sfi ... stackframe info to start stacktrace from
513 stacktrace as Java byte-array
515 *******************************************************************************/
517 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
519 stackframeinfo_t tmpsfi;
521 java_handle_bytearray_t *ba;
524 stacktrace_entry_t *ste;
526 bool skip_fillInStackTrace;
529 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
532 if (opt_DebugStackTrace)
533 log_println("[stacktrace_get]");
536 skip_fillInStackTrace = true;
539 depth = stacktrace_depth(sfi);
544 /* Allocate memory from the GC heap and copy the stacktrace
546 /* ATTENTION: Use a Java byte-array for this to not confuse the
548 /* FIXME: We waste some memory here as we skip some entries
551 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
553 ba = builtin_newarray_byte(ba_size);
558 /* Get a stacktrace entry pointer. */
559 /* ATTENTION: We need a critical section here because we use the
560 byte-array data pointer directly. */
564 st = (stacktrace_t *) LLNI_array_data(ba);
568 /* Iterate over the whole stack. */
570 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
571 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
572 stacktrace_stackframeinfo_next(&tmpsfi)) {
573 /* Get the methodinfo. */
577 /* Skip builtin methods. */
579 if (m->flags & ACC_METHOD_BUILTIN)
582 /* This logic is taken from
583 hotspot/src/share/vm/classfile/javaClasses.cpp
584 (java_lang_Throwable::fill_in_stack_trace). */
586 if (skip_fillInStackTrace == true) {
587 /* Check "fillInStackTrace" only once, so we negate the
588 flag after the first time check. */
590 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
591 /* For GNU Classpath we also need to skip
592 VMThrowable.fillInStackTrace(). */
594 if ((m->clazz == class_java_lang_VMThrowable) &&
595 (m->name == utf_fillInStackTrace))
599 skip_fillInStackTrace = false;
601 if (m->name == utf_fillInStackTrace)
605 /* Skip <init> methods of the exceptions klass. If there is
606 <init> methods that belongs to a superclass of the
607 exception we are going to skipping them in stack trace. */
609 if (skip_init == true) {
610 if ((m->name == utf_init) &&
611 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
615 /* If no "Throwable.init()" method found, we stop
616 checking it next time. */
622 /* Store the stacktrace entry and increment the pointer. */
624 ste->code = tmpsfi.code;
625 ste->pc = tmpsfi.xpc;
630 /* Store the number of entries in the stacktrace structure. */
632 st->length = ste - st->entries;
636 /* release dump memory */
638 /* dump_release(dumpsize); */
640 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
645 /* dump_release(dumpsize); */
647 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
654 /* stacktrace_get_current ******************************************************
656 Builds and returns a stacktrace from the current thread and returns
657 the stacktrace structure wrapped in a Java byte-array to not
661 stacktrace as Java byte-array
663 *******************************************************************************/
665 java_handle_bytearray_t *stacktrace_get_current(void)
667 stackframeinfo_t *sfi;
668 java_handle_bytearray_t *ba;
670 sfi = threads_get_current_stackframeinfo();
671 ba = stacktrace_get(sfi);
678 * Creates a java.lang.StackTraceElement for one element of the given
681 * @param st Given stacktrace.
682 * @param index Index of element inside stacktrace.
683 * @return The filled StackTraceElement object.
685 #if defined(ENABLE_JAVASE)
686 java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t* st, int32_t index)
690 if ((index < 0) || (index >= st->length)) {
691 /* XXX This should be an IndexOutOfBoundsException (check this
693 exceptions_throw_arrayindexoutofboundsexception();
697 // Get the stacktrace entry.
698 stacktrace_entry_t* ste = &(st->entries[index]);
700 // Get the codeinfo, methodinfo and classinfo.
701 codeinfo* code = ste->code;
702 methodinfo* m = code->m;
703 classinfo* c = m->clazz;
706 java_handle_t* filename;
708 if (!(m->flags & ACC_NATIVE)) {
709 if (c->sourcefile != NULL)
710 filename = javastring_new(c->sourcefile);
720 if (m->flags & ACC_NATIVE) {
721 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
723 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
726 # error unknown classpath configuration
730 // FIXME linenumbertable->find could change the methodinfo
731 // pointer when hitting an inlined method.
732 linenumber = code->linenumbertable->find(&m, ste->pc);
733 linenumber = (linenumber == 0) ? -1 : linenumber;
736 // Get declaring class name.
737 java_handle_t* declaringclass = class_get_classname(c);
739 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
740 // Allocate a new StackTraceElement object.
741 java_handle_t* h = builtin_new(class_java_lang_StackTraceElement);
746 java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0));
747 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
748 // Allocate a new StackTraceElement object.
749 java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber);
754 # error unknown classpath configuration
757 return jlste.get_handle();
763 * Creates a complete array of java.lang.StackTraceElement objects
764 * for the given stacktrace.
766 * @param st Given stacktrace.
767 * @return Array of filled StackTraceElement objects.
769 #if defined(ENABLE_JAVASE)
770 java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st)
772 // Get length of stacktrace. If stacktrace is not available
773 // an empty array should be returned.
774 int32_t length = (st != NULL) ? st->length : 0;
776 // Create the stacktrace element array.
777 java_handle_objectarray_t* oa = builtin_anewarray(length, class_java_lang_StackTraceElement);
782 // Iterate over all stacktrace elements.
783 for (int i = 0; i < length; i++) {
785 // Get stacktrace element at current index.
786 java_handle_t* h = stacktrace_get_StackTraceElement(st, i);
791 // Store stacktrace element in array.
792 array_objectarray_element_set(oa, i, h);
800 /* stacktrace_get_caller_class *************************************************
802 Get the class on the stack at the given depth. This function skips
803 various special classes or methods.
806 depth ... depth to get caller class of
811 *******************************************************************************/
813 #if defined(ENABLE_JAVASE)
814 classinfo *stacktrace_get_caller_class(int depth)
816 stackframeinfo_t *sfi;
817 stackframeinfo_t tmpsfi;
823 if (opt_DebugStackTrace)
824 log_println("[stacktrace_get_caller_class]");
827 /* Get the stackframeinfo of the current thread. */
829 sfi = threads_get_current_stackframeinfo();
831 /* Iterate over the whole stack until we reached the requested
836 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
837 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
838 stacktrace_stackframeinfo_next(&tmpsfi)) {
843 /* Skip builtin methods. */
845 if (m->flags & ACC_METHOD_BUILTIN)
848 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
849 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
850 (vframeStreamCommon::security_get_caller_frame). */
852 /* This is java.lang.reflect.Method.invoke(), skip it. */
854 if (m == method_java_lang_reflect_Method_invoke)
857 /* This is an auxiliary frame, skip it. */
859 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
863 /* We reached the requested depth. */
876 /* stacktrace_first_nonnull_classloader ****************************************
878 Returns the first non-null (user-defined) classloader on the stack.
879 If none is found NULL is returned.
884 *******************************************************************************/
886 classloader_t *stacktrace_first_nonnull_classloader(void)
888 stackframeinfo_t *sfi;
889 stackframeinfo_t tmpsfi;
894 if (opt_DebugStackTrace)
895 log_println("[stacktrace_first_nonnull_classloader]");
898 /* Get the stackframeinfo of the current thread. */
900 sfi = threads_get_current_stackframeinfo();
902 /* Iterate over the whole stack. */
904 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
905 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
906 stacktrace_stackframeinfo_next(&tmpsfi)) {
909 cl = class_get_classloader(m->clazz);
919 /* stacktrace_getClassContext **************************************************
921 Creates a Class context array.
924 the array of java.lang.Class objects, or
925 NULL if an exception has been thrown
927 *******************************************************************************/
929 java_handle_objectarray_t *stacktrace_getClassContext(void)
931 stackframeinfo_t *sfi;
932 stackframeinfo_t tmpsfi;
934 java_handle_objectarray_t *oa;
935 java_object_t **data;
939 CYCLES_STATS_DECLARE_AND_START
942 if (opt_DebugStackTrace)
943 log_println("[stacktrace_getClassContext]");
946 sfi = threads_get_current_stackframeinfo();
948 /* Get the depth of the current stack. */
950 depth = stacktrace_depth(sfi);
952 /* The first stackframe corresponds to the method whose
953 implementation calls this native function. We remove that
957 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
958 stacktrace_stackframeinfo_next(&tmpsfi);
960 /* Allocate the Class array. */
962 oa = builtin_anewarray(depth, class_java_lang_Class);
965 CYCLES_STATS_END(stacktrace_getClassContext);
970 /* Fill the Class array from the stacktrace list. */
974 data = LLNI_array_data(oa);
976 /* Iterate over the whole stack. */
981 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
982 stacktrace_stackframeinfo_next(&tmpsfi)) {
983 /* Get methodinfo. */
987 /* Skip builtin methods. */
989 if (m->flags & ACC_METHOD_BUILTIN)
992 /* Store the class in the array. */
994 data[i] = (java_object_t *) m->clazz;
1001 CYCLES_STATS_END(stacktrace_getClassContext)
1007 /* stacktrace_getCurrentClass **************************************************
1009 Find the current class by walking the stack trace.
1011 Quote from the JNI documentation:
1013 In the Java 2 Platform, FindClass locates the class loader
1014 associated with the current native method. If the native code
1015 belongs to a system class, no class loader will be
1016 involved. Otherwise, the proper class loader will be invoked to
1017 load and link the named class. When FindClass is called through the
1018 Invocation Interface, there is no current native method or its
1019 associated class loader. In that case, the result of
1020 ClassLoader.getBaseClassLoader is used."
1022 *******************************************************************************/
1024 #if defined(ENABLE_JAVASE)
1025 classinfo *stacktrace_get_current_class(void)
1027 stackframeinfo_t *sfi;
1028 stackframeinfo_t tmpsfi;
1031 CYCLES_STATS_DECLARE_AND_START;
1033 #if !defined(NDEBUG)
1034 if (opt_DebugStackTrace)
1035 log_println("[stacktrace_get_current_class]");
1038 /* Get the stackframeinfo of the current thread. */
1040 sfi = threads_get_current_stackframeinfo();
1042 /* If the stackframeinfo is NULL then FindClass is called through
1043 the Invocation Interface and we return NULL */
1046 CYCLES_STATS_END(stacktrace_getCurrentClass);
1051 /* Iterate over the whole stack. */
1053 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1054 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1055 stacktrace_stackframeinfo_next(&tmpsfi)) {
1056 /* Get the methodinfo. */
1060 if (m->clazz == class_java_security_PrivilegedAction) {
1061 CYCLES_STATS_END(stacktrace_getCurrentClass);
1066 if (m->clazz != NULL) {
1067 CYCLES_STATS_END(stacktrace_getCurrentClass);
1073 /* No Java method found on the stack. */
1075 CYCLES_STATS_END(stacktrace_getCurrentClass);
1079 #endif /* ENABLE_JAVASE */
1082 /* stacktrace_get_stack ********************************************************
1084 Create a 2-dimensional array for java.security.VMAccessControler.
1088 NULL if an exception has been thrown
1090 *******************************************************************************/
1092 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1093 java_handle_objectarray_t *stacktrace_get_stack(void)
1095 stackframeinfo_t *sfi;
1096 stackframeinfo_t tmpsfi;
1098 java_handle_objectarray_t *oa;
1099 java_handle_objectarray_t *classes;
1100 java_handle_objectarray_t *methodnames;
1102 java_handle_t *string;
1105 CYCLES_STATS_DECLARE_AND_START
1107 #if !defined(NDEBUG)
1108 if (opt_DebugStackTrace)
1109 log_println("[stacktrace_get_stack]");
1112 /* Get the stackframeinfo of the current thread. */
1114 sfi = threads_get_current_stackframeinfo();
1116 /* Get the depth of the current stack. */
1118 depth = stacktrace_depth(sfi);
1123 /* Allocate the required arrays. */
1125 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1130 classes = builtin_anewarray(depth, class_java_lang_Class);
1132 if (classes == NULL)
1135 methodnames = builtin_anewarray(depth, class_java_lang_String);
1137 if (methodnames == NULL)
1140 /* Set up the 2-dimensional array. */
1142 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1143 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1145 /* Iterate over the whole stack. */
1146 /* TODO We should use a critical section here to speed things
1151 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1152 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1153 stacktrace_stackframeinfo_next(&tmpsfi)) {
1154 /* Get the methodinfo. */
1158 /* Skip builtin methods. */
1160 if (m->flags & ACC_METHOD_BUILTIN)
1163 /* Store the class in the array. */
1164 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1167 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1169 /* Store the name in the array. */
1171 string = javastring_new(m->name);
1176 array_objectarray_element_set(methodnames, i, string);
1181 CYCLES_STATS_END(stacktrace_get_stack)
1186 CYCLES_STATS_END(stacktrace_get_stack)
1193 /* stacktrace_print_entry ****************************************************
1195 Print line for a stacktrace entry.
1198 m ............ methodinfo of the entry
1199 linenumber ... linenumber of the entry
1201 *******************************************************************************/
1203 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1211 if (m->flags & ACC_METHOD_BUILTIN)
1214 utf_display_printable_ascii_classname(m->clazz->name);
1217 utf_display_printable_ascii(m->name);
1218 utf_display_printable_ascii(m->descriptor);
1220 if (m->flags & ACC_NATIVE) {
1221 puts("(Native Method)");
1224 if (m->flags & ACC_METHOD_BUILTIN) {
1229 utf_display_printable_ascii(m->clazz->sourcefile);
1230 printf(":%d)\n", linenumber);
1238 /* stacktrace_print ************************************************************
1240 Print the given stacktrace with CACAO intern methods only (no Java
1243 This method is used by stacktrace_dump_trace and
1244 builtin_trace_exception.
1247 st ... stacktrace to print
1249 *******************************************************************************/
1251 void stacktrace_print(stacktrace_t *st)
1253 stacktrace_entry_t *ste;
1258 ste = &(st->entries[0]);
1260 for (i = 0; i < st->length; i++, ste++) {
1263 /* Get the line number. */
1265 linenumber = ste->code->linenumbertable->find(&m, ste->pc);
1267 stacktrace_print_entry(m, linenumber);
1272 /* stacktrace_print_current ****************************************************
1274 Print the current stacktrace of the current thread.
1276 NOTE: This function prints all frames of the stacktrace and does
1277 not skip frames like stacktrace_get.
1279 *******************************************************************************/
1281 void stacktrace_print_current(void)
1283 stackframeinfo_t *sfi;
1284 stackframeinfo_t tmpsfi;
1289 sfi = threads_get_current_stackframeinfo();
1292 puts("\t<<No stacktrace available>>");
1297 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1298 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1299 stacktrace_stackframeinfo_next(&tmpsfi)) {
1300 /* Get the methodinfo. */
1305 // Get the line number.
1306 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1308 stacktrace_print_entry(m, linenumber);
1314 * Creates a stacktrace for the given thread.
1316 * @param t Given thread.
1317 * @return Current stacktrace of the given thread.
1319 * XXX: Creation of the stacktrace starts at the most recent
1320 * stackframeinfo block. If the thread is not inside the native
1321 * world, the created stacktrace is not complete!
1323 #if defined(ENABLE_THREADS)
1324 stacktrace_t* stacktrace_get_of_thread(threadobject* t)
1326 stackframeinfo_t* sfi;
1327 java_handle_bytearray_t* ba;
1330 sfi = t->_stackframeinfo;
1331 ba = stacktrace_get(sfi);
1336 st = (stacktrace_t*) LLNI_array_data(ba);
1343 /* stacktrace_print_of_thread **************************************************
1345 Print the current stacktrace of the given thread.
1350 *******************************************************************************/
1352 #if defined(ENABLE_THREADS)
1353 void stacktrace_print_of_thread(threadobject *t)
1355 stackframeinfo_t *sfi;
1356 stackframeinfo_t tmpsfi;
1361 /* Build a stacktrace for the passed thread. */
1363 sfi = t->_stackframeinfo;
1366 puts("\t<<No stacktrace available>>");
1371 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1372 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1373 stacktrace_stackframeinfo_next(&tmpsfi)) {
1374 /* Get the methodinfo. */
1379 // Get the line number.
1380 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1382 stacktrace_print_entry(m, linenumber);
1388 /* stacktrace_print_exception **************************************************
1390 Print the stacktrace of a given exception (more or less a wrapper
1391 to stacktrace_print).
1394 h ... handle of exception to print
1396 *******************************************************************************/
1398 void stacktrace_print_exception(java_handle_t *h)
1403 java_lang_Throwable t(h);
1405 /* now print the stacktrace */
1407 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1409 java_lang_VMThrowable vmt(t.get_vmState());
1410 java_handle_bytearray_t* backtrace = vmt.get_vmdata();
1412 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1414 java_handle_bytearray_t* backtrace = t.get_backtrace();
1417 # error unknown classpath configuration
1422 assert(backtrace != NULL);
1424 /* We need a critical section here as we use the byte-array data
1425 pointer directly. */
1427 LLNI_CRITICAL_START;
1429 stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
1431 stacktrace_print(st);
1437 #if defined(ENABLE_CYCLES_STATS)
1438 void stacktrace_print_cycles_stats(FILE *file)
1440 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1441 CYCLES_STATS_PRINT(stacktrace_get, file);
1442 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1443 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1444 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1452 * These are local overrides for various environment variables in Emacs.
1453 * Please do not remove this and leave it at the end of the file, where
1454 * Emacs will automagically detect them.
1455 * ---------------------------------------------------------------------
1458 * indent-tabs-mode: t
1462 * vim:noexpandtab:sw=4:ts=4: