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)
688 if ((index < 0) || (index >= st->length)) {
689 /* XXX This should be an IndexOutOfBoundsException (check this
691 exceptions_throw_arrayindexoutofboundsexception();
695 // Get the stacktrace entry.
696 stacktrace_entry_t* ste = &(st->entries[index]);
698 // Get the codeinfo, methodinfo and classinfo.
699 codeinfo* code = ste->code;
700 methodinfo* m = code->m;
701 classinfo* c = m->clazz;
704 java_handle_t* filename;
706 if (!(m->flags & ACC_NATIVE)) {
707 if (c->sourcefile != NULL)
708 filename = javastring_new(c->sourcefile);
718 if (m->flags & ACC_NATIVE) {
719 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
721 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
724 # error unknown classpath configuration
728 // FIXME linenumbertable->find could change the methodinfo
729 // pointer when hitting an inlined method.
730 linenumber = code->linenumbertable->find(&m, ste->pc);
731 linenumber = (linenumber == 0) ? -1 : linenumber;
734 // Get declaring class name.
735 java_handle_t* declaringclass = class_get_classname(c);
737 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
738 // Allocate a new StackTraceElement object.
739 java_handle_t* h = builtin_new(class_java_lang_StackTraceElement);
744 java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0));
745 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
746 // Allocate a new StackTraceElement object.
747 java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber);
752 # error unknown classpath configuration
755 return jlste.get_handle();
761 * Creates a complete array of java.lang.StackTraceElement objects
762 * for the given stacktrace.
764 * @param st Given stacktrace.
765 * @return Array of filled StackTraceElement objects.
767 #if defined(ENABLE_JAVASE)
768 java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st)
770 // Create the stacktrace element array.
771 java_handle_objectarray_t* oa = builtin_anewarray(st->length, class_java_lang_StackTraceElement);
776 // Iterate over all stacktrace elements.
777 for (int i = 0; i < st->length; i++) {
779 // Get stacktrace element at current index.
780 java_handle_t* h = stacktrace_get_StackTraceElement(st, i);
785 // Store stacktrace element in array.
786 array_objectarray_element_set(oa, i, h);
794 /* stacktrace_get_caller_class *************************************************
796 Get the class on the stack at the given depth. This function skips
797 various special classes or methods.
800 depth ... depth to get caller class of
805 *******************************************************************************/
807 #if defined(ENABLE_JAVASE)
808 classinfo *stacktrace_get_caller_class(int depth)
810 stackframeinfo_t *sfi;
811 stackframeinfo_t tmpsfi;
817 if (opt_DebugStackTrace)
818 log_println("[stacktrace_get_caller_class]");
821 /* Get the stackframeinfo of the current thread. */
823 sfi = threads_get_current_stackframeinfo();
825 /* Iterate over the whole stack until we reached the requested
830 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
831 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
832 stacktrace_stackframeinfo_next(&tmpsfi)) {
837 /* Skip builtin methods. */
839 if (m->flags & ACC_METHOD_BUILTIN)
842 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
843 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
844 (vframeStreamCommon::security_get_caller_frame). */
846 /* This is java.lang.reflect.Method.invoke(), skip it. */
848 if (m == method_java_lang_reflect_Method_invoke)
851 /* This is an auxiliary frame, skip it. */
853 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
857 /* We reached the requested depth. */
870 /* stacktrace_first_nonnull_classloader ****************************************
872 Returns the first non-null (user-defined) classloader on the stack.
873 If none is found NULL is returned.
878 *******************************************************************************/
880 classloader_t *stacktrace_first_nonnull_classloader(void)
882 stackframeinfo_t *sfi;
883 stackframeinfo_t tmpsfi;
888 if (opt_DebugStackTrace)
889 log_println("[stacktrace_first_nonnull_classloader]");
892 /* Get the stackframeinfo of the current thread. */
894 sfi = threads_get_current_stackframeinfo();
896 /* Iterate over the whole stack. */
898 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
899 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
900 stacktrace_stackframeinfo_next(&tmpsfi)) {
903 cl = class_get_classloader(m->clazz);
913 /* stacktrace_getClassContext **************************************************
915 Creates a Class context array.
918 the array of java.lang.Class objects, or
919 NULL if an exception has been thrown
921 *******************************************************************************/
923 java_handle_objectarray_t *stacktrace_getClassContext(void)
925 stackframeinfo_t *sfi;
926 stackframeinfo_t tmpsfi;
928 java_handle_objectarray_t *oa;
929 java_object_t **data;
933 CYCLES_STATS_DECLARE_AND_START
936 if (opt_DebugStackTrace)
937 log_println("[stacktrace_getClassContext]");
940 sfi = threads_get_current_stackframeinfo();
942 /* Get the depth of the current stack. */
944 depth = stacktrace_depth(sfi);
946 /* The first stackframe corresponds to the method whose
947 implementation calls this native function. We remove that
951 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
952 stacktrace_stackframeinfo_next(&tmpsfi);
954 /* Allocate the Class array. */
956 oa = builtin_anewarray(depth, class_java_lang_Class);
959 CYCLES_STATS_END(stacktrace_getClassContext);
964 /* Fill the Class array from the stacktrace list. */
968 data = LLNI_array_data(oa);
970 /* Iterate over the whole stack. */
975 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
976 stacktrace_stackframeinfo_next(&tmpsfi)) {
977 /* Get methodinfo. */
981 /* Skip builtin methods. */
983 if (m->flags & ACC_METHOD_BUILTIN)
986 /* Store the class in the array. */
988 data[i] = (java_object_t *) m->clazz;
995 CYCLES_STATS_END(stacktrace_getClassContext)
1001 /* stacktrace_getCurrentClass **************************************************
1003 Find the current class by walking the stack trace.
1005 Quote from the JNI documentation:
1007 In the Java 2 Platform, FindClass locates the class loader
1008 associated with the current native method. If the native code
1009 belongs to a system class, no class loader will be
1010 involved. Otherwise, the proper class loader will be invoked to
1011 load and link the named class. When FindClass is called through the
1012 Invocation Interface, there is no current native method or its
1013 associated class loader. In that case, the result of
1014 ClassLoader.getBaseClassLoader is used."
1016 *******************************************************************************/
1018 #if defined(ENABLE_JAVASE)
1019 classinfo *stacktrace_get_current_class(void)
1021 stackframeinfo_t *sfi;
1022 stackframeinfo_t tmpsfi;
1025 CYCLES_STATS_DECLARE_AND_START;
1027 #if !defined(NDEBUG)
1028 if (opt_DebugStackTrace)
1029 log_println("[stacktrace_get_current_class]");
1032 /* Get the stackframeinfo of the current thread. */
1034 sfi = threads_get_current_stackframeinfo();
1036 /* If the stackframeinfo is NULL then FindClass is called through
1037 the Invocation Interface and we return NULL */
1040 CYCLES_STATS_END(stacktrace_getCurrentClass);
1045 /* Iterate over the whole stack. */
1047 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1048 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1049 stacktrace_stackframeinfo_next(&tmpsfi)) {
1050 /* Get the methodinfo. */
1054 if (m->clazz == class_java_security_PrivilegedAction) {
1055 CYCLES_STATS_END(stacktrace_getCurrentClass);
1060 if (m->clazz != NULL) {
1061 CYCLES_STATS_END(stacktrace_getCurrentClass);
1067 /* No Java method found on the stack. */
1069 CYCLES_STATS_END(stacktrace_getCurrentClass);
1073 #endif /* ENABLE_JAVASE */
1076 /* stacktrace_get_stack ********************************************************
1078 Create a 2-dimensional array for java.security.VMAccessControler.
1082 NULL if an exception has been thrown
1084 *******************************************************************************/
1086 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1087 java_handle_objectarray_t *stacktrace_get_stack(void)
1089 stackframeinfo_t *sfi;
1090 stackframeinfo_t tmpsfi;
1092 java_handle_objectarray_t *oa;
1093 java_handle_objectarray_t *classes;
1094 java_handle_objectarray_t *methodnames;
1096 java_handle_t *string;
1099 CYCLES_STATS_DECLARE_AND_START
1101 #if !defined(NDEBUG)
1102 if (opt_DebugStackTrace)
1103 log_println("[stacktrace_get_stack]");
1106 /* Get the stackframeinfo of the current thread. */
1108 sfi = threads_get_current_stackframeinfo();
1110 /* Get the depth of the current stack. */
1112 depth = stacktrace_depth(sfi);
1117 /* Allocate the required arrays. */
1119 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1124 classes = builtin_anewarray(depth, class_java_lang_Class);
1126 if (classes == NULL)
1129 methodnames = builtin_anewarray(depth, class_java_lang_String);
1131 if (methodnames == NULL)
1134 /* Set up the 2-dimensional array. */
1136 array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1137 array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1139 /* Iterate over the whole stack. */
1140 /* TODO We should use a critical section here to speed things
1145 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1146 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1147 stacktrace_stackframeinfo_next(&tmpsfi)) {
1148 /* Get the methodinfo. */
1152 /* Skip builtin methods. */
1154 if (m->flags & ACC_METHOD_BUILTIN)
1157 /* Store the class in the array. */
1158 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1161 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1163 /* Store the name in the array. */
1165 string = javastring_new(m->name);
1170 array_objectarray_element_set(methodnames, i, string);
1175 CYCLES_STATS_END(stacktrace_get_stack)
1180 CYCLES_STATS_END(stacktrace_get_stack)
1187 /* stacktrace_print_entry ****************************************************
1189 Print line for a stacktrace entry.
1192 m ............ methodinfo of the entry
1193 linenumber ... linenumber of the entry
1195 *******************************************************************************/
1197 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1205 if (m->flags & ACC_METHOD_BUILTIN)
1208 utf_display_printable_ascii_classname(m->clazz->name);
1211 utf_display_printable_ascii(m->name);
1212 utf_display_printable_ascii(m->descriptor);
1214 if (m->flags & ACC_NATIVE) {
1215 puts("(Native Method)");
1218 if (m->flags & ACC_METHOD_BUILTIN) {
1223 utf_display_printable_ascii(m->clazz->sourcefile);
1224 printf(":%d)\n", linenumber);
1232 /* stacktrace_print ************************************************************
1234 Print the given stacktrace with CACAO intern methods only (no Java
1237 This method is used by stacktrace_dump_trace and
1238 builtin_trace_exception.
1241 st ... stacktrace to print
1243 *******************************************************************************/
1245 void stacktrace_print(stacktrace_t *st)
1247 stacktrace_entry_t *ste;
1252 ste = &(st->entries[0]);
1254 for (i = 0; i < st->length; i++, ste++) {
1257 /* Get the line number. */
1259 linenumber = ste->code->linenumbertable->find(&m, ste->pc);
1261 stacktrace_print_entry(m, linenumber);
1266 /* stacktrace_print_current ****************************************************
1268 Print the current stacktrace of the current thread.
1270 NOTE: This function prints all frames of the stacktrace and does
1271 not skip frames like stacktrace_get.
1273 *******************************************************************************/
1275 void stacktrace_print_current(void)
1277 stackframeinfo_t *sfi;
1278 stackframeinfo_t tmpsfi;
1283 sfi = threads_get_current_stackframeinfo();
1286 puts("\t<<No stacktrace available>>");
1291 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1292 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1293 stacktrace_stackframeinfo_next(&tmpsfi)) {
1294 /* Get the methodinfo. */
1299 // Get the line number.
1300 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1302 stacktrace_print_entry(m, linenumber);
1308 * Creates a stacktrace for the given thread.
1310 * @param t Given thread.
1311 * @return Current stacktrace of the given thread.
1313 * XXX: Creation of the stacktrace starts at the most recent
1314 * stackframeinfo block. If the thread is not inside the native
1315 * world, the created stacktrace is not complete!
1317 #if defined(ENABLE_THREADS)
1318 stacktrace_t* stacktrace_get_of_thread(threadobject* t)
1320 stackframeinfo_t* sfi;
1321 java_handle_bytearray_t* ba;
1324 sfi = t->_stackframeinfo;
1325 ba = stacktrace_get(sfi);
1330 st = (stacktrace_t*) LLNI_array_data(ba);
1337 /* stacktrace_print_of_thread **************************************************
1339 Print the current stacktrace of the given thread.
1344 *******************************************************************************/
1346 #if defined(ENABLE_THREADS)
1347 void stacktrace_print_of_thread(threadobject *t)
1349 stackframeinfo_t *sfi;
1350 stackframeinfo_t tmpsfi;
1355 /* Build a stacktrace for the passed thread. */
1357 sfi = t->_stackframeinfo;
1360 puts("\t<<No stacktrace available>>");
1365 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1366 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1367 stacktrace_stackframeinfo_next(&tmpsfi)) {
1368 /* Get the methodinfo. */
1373 // Get the line number.
1374 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1376 stacktrace_print_entry(m, linenumber);
1382 /* stacktrace_print_exception **************************************************
1384 Print the stacktrace of a given exception (more or less a wrapper
1385 to stacktrace_print).
1388 h ... handle of exception to print
1390 *******************************************************************************/
1392 void stacktrace_print_exception(java_handle_t *h)
1397 java_lang_Throwable t(h);
1399 /* now print the stacktrace */
1401 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1403 java_lang_VMThrowable vmt(t.get_vmState());
1404 java_handle_bytearray_t* backtrace = vmt.get_vmdata();
1406 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1408 java_handle_bytearray_t* backtrace = t.get_backtrace();
1411 # error unknown classpath configuration
1416 assert(backtrace != NULL);
1418 /* We need a critical section here as we use the byte-array data
1419 pointer directly. */
1421 LLNI_CRITICAL_START;
1423 stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
1425 stacktrace_print(st);
1431 #if defined(ENABLE_CYCLES_STATS)
1432 void stacktrace_print_cycles_stats(FILE *file)
1434 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1435 CYCLES_STATS_PRINT(stacktrace_get, file);
1436 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1437 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1438 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1446 * These are local overrides for various environment variables in Emacs.
1447 * Please do not remove this and leave it at the end of the file, where
1448 * Emacs will automagically detect them.
1449 * ---------------------------------------------------------------------
1452 * indent-tabs-mode: t
1456 * vim:noexpandtab:sw=4:ts=4: