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;
523 stacktrace_entry_t *ste;
525 bool skip_fillInStackTrace;
528 CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
531 if (opt_DebugStackTrace)
532 log_println("[stacktrace_get]");
535 skip_fillInStackTrace = true;
538 depth = stacktrace_depth(sfi);
543 /* Allocate memory from the GC heap and copy the stacktrace
545 /* ATTENTION: Use a Java byte-array for this to not confuse the
547 /* FIXME: We waste some memory here as we skip some entries
550 ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
552 ByteArray ba(ba_size);
557 /* Get a stacktrace entry pointer. */
558 /* ATTENTION: We need a critical section here because we use the
559 byte-array data pointer directly. */
563 st = (stacktrace_t *) ba.get_raw_data_ptr();
567 /* Iterate over the whole stack. */
569 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
570 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
571 stacktrace_stackframeinfo_next(&tmpsfi)) {
572 /* Get the methodinfo. */
576 /* Skip builtin methods. */
578 if (m->flags & ACC_METHOD_BUILTIN)
581 /* This logic is taken from
582 hotspot/src/share/vm/classfile/javaClasses.cpp
583 (java_lang_Throwable::fill_in_stack_trace). */
585 if (skip_fillInStackTrace == true) {
586 /* Check "fillInStackTrace" only once, so we negate the
587 flag after the first time check. */
589 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
590 /* For GNU Classpath we also need to skip
591 VMThrowable.fillInStackTrace(). */
593 if ((m->clazz == class_java_lang_VMThrowable) &&
594 (m->name == utf_fillInStackTrace))
598 skip_fillInStackTrace = false;
600 if (m->name == utf_fillInStackTrace)
604 /* Skip <init> methods of the exceptions klass. If there is
605 <init> methods that belongs to a superclass of the
606 exception we are going to skipping them in stack trace. */
608 if (skip_init == true) {
609 if ((m->name == utf_init) &&
610 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
614 /* If no "Throwable.init()" method found, we stop
615 checking it next time. */
621 /* Store the stacktrace entry and increment the pointer. */
623 ste->code = tmpsfi.code;
624 ste->pc = tmpsfi.xpc;
629 /* Store the number of entries in the stacktrace structure. */
631 st->length = ste - st->entries;
635 /* release dump memory */
637 /* dump_release(dumpsize); */
639 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
641 return ba.get_handle();
644 /* dump_release(dumpsize); */
646 CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
653 /* stacktrace_get_current ******************************************************
655 Builds and returns a stacktrace from the current thread and returns
656 the stacktrace structure wrapped in a Java byte-array to not
660 stacktrace as Java byte-array
662 *******************************************************************************/
664 java_handle_bytearray_t *stacktrace_get_current(void)
666 stackframeinfo_t *sfi;
667 java_handle_bytearray_t *ba;
669 sfi = threads_get_current_stackframeinfo();
670 ba = stacktrace_get(sfi);
677 * Creates a java.lang.StackTraceElement for one element of the given
680 * @param st Given stacktrace.
681 * @param index Index of element inside stacktrace.
682 * @return The filled StackTraceElement object.
684 #if defined(ENABLE_JAVASE)
685 java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t* st, int32_t index)
689 if ((index < 0) || (index >= st->length)) {
690 /* XXX This should be an IndexOutOfBoundsException (check this
692 exceptions_throw_arrayindexoutofboundsexception();
696 // Get the stacktrace entry.
697 stacktrace_entry_t* ste = &(st->entries[index]);
699 // Get the codeinfo, methodinfo and classinfo.
700 codeinfo* code = ste->code;
701 methodinfo* m = code->m;
702 classinfo* c = m->clazz;
705 java_handle_t* filename;
707 if (!(m->flags & ACC_NATIVE)) {
708 if (c->sourcefile != NULL)
709 filename = javastring_new(c->sourcefile);
719 if (m->flags & ACC_NATIVE) {
720 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
722 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
725 # error unknown classpath configuration
729 // FIXME linenumbertable->find could change the methodinfo
730 // pointer when hitting an inlined method.
731 linenumber = code->linenumbertable->find(&m, ste->pc);
732 linenumber = (linenumber == 0) ? -1 : linenumber;
735 // Get declaring class name.
736 java_handle_t* declaringclass = class_get_classname(c);
738 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
739 // Allocate a new StackTraceElement object.
740 java_handle_t* h = builtin_new(class_java_lang_StackTraceElement);
745 java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0));
746 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
747 // Allocate a new StackTraceElement object.
748 java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber);
753 # error unknown classpath configuration
756 return jlste.get_handle();
762 * Creates a complete array of java.lang.StackTraceElement objects
763 * for the given stacktrace.
765 * @param st Given stacktrace.
766 * @return Array of filled StackTraceElement objects.
768 #if defined(ENABLE_JAVASE)
769 java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st)
771 // Get length of stacktrace. If stacktrace is not available
772 // an empty array should be returned.
773 int32_t length = (st != NULL) ? st->length : 0;
775 // Create the stacktrace element array.
776 ObjectArray oa(length, class_java_lang_StackTraceElement);
781 // Iterate over all stacktrace elements.
782 for (int i = 0; i < length; i++) {
784 // Get stacktrace element at current index.
785 java_handle_t* h = stacktrace_get_StackTraceElement(st, i);
790 // Store stacktrace element in array.
791 oa.set_element(i, h);
794 return oa.get_handle();
799 /* stacktrace_get_caller_class *************************************************
801 Get the class on the stack at the given depth. This function skips
802 various special classes or methods.
805 depth ... depth to get caller class of
810 *******************************************************************************/
812 #if defined(ENABLE_JAVASE)
813 classinfo *stacktrace_get_caller_class(int depth)
815 stackframeinfo_t *sfi;
816 stackframeinfo_t tmpsfi;
822 if (opt_DebugStackTrace)
823 log_println("[stacktrace_get_caller_class]");
826 /* Get the stackframeinfo of the current thread. */
828 sfi = threads_get_current_stackframeinfo();
830 /* Iterate over the whole stack until we reached the requested
835 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
836 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
837 stacktrace_stackframeinfo_next(&tmpsfi)) {
842 /* Skip builtin methods. */
844 if (m->flags & ACC_METHOD_BUILTIN)
847 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
848 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
849 (vframeStreamCommon::security_get_caller_frame). */
851 /* This is java.lang.reflect.Method.invoke(), skip it. */
853 if (m == method_java_lang_reflect_Method_invoke)
856 /* This is an auxiliary frame, skip it. */
858 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
862 /* We reached the requested depth. */
875 /* stacktrace_first_nonnull_classloader ****************************************
877 Returns the first non-null (user-defined) classloader on the stack.
878 If none is found NULL is returned.
883 *******************************************************************************/
885 classloader_t *stacktrace_first_nonnull_classloader(void)
887 stackframeinfo_t *sfi;
888 stackframeinfo_t tmpsfi;
893 if (opt_DebugStackTrace)
894 log_println("[stacktrace_first_nonnull_classloader]");
897 /* Get the stackframeinfo of the current thread. */
899 sfi = threads_get_current_stackframeinfo();
901 /* Iterate over the whole stack. */
903 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
904 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
905 stacktrace_stackframeinfo_next(&tmpsfi)) {
908 cl = class_get_classloader(m->clazz);
918 /* stacktrace_getClassContext **************************************************
920 Creates a Class context array.
923 the array of java.lang.Class objects, or
924 NULL if an exception has been thrown
926 *******************************************************************************/
928 java_handle_objectarray_t *stacktrace_getClassContext(void)
930 stackframeinfo_t *sfi;
931 stackframeinfo_t tmpsfi;
936 CYCLES_STATS_DECLARE_AND_START
939 if (opt_DebugStackTrace)
940 log_println("[stacktrace_getClassContext]");
943 sfi = threads_get_current_stackframeinfo();
945 /* Get the depth of the current stack. */
947 depth = stacktrace_depth(sfi);
949 /* The first stackframe corresponds to the method whose
950 implementation calls this native function. We remove that
954 stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
955 stacktrace_stackframeinfo_next(&tmpsfi);
957 /* Allocate the Class array. */
959 ClassArray ca(depth);
962 CYCLES_STATS_END(stacktrace_getClassContext);
967 /* Fill the Class array from the stacktrace list. */
968 /* Iterate over the whole stack. */
973 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
974 stacktrace_stackframeinfo_next(&tmpsfi)) {
975 /* Get methodinfo. */
979 /* Skip builtin methods. */
981 if (m->flags & ACC_METHOD_BUILTIN)
984 /* Store the class in the array. */
986 ca.set_element(i, m->clazz);
993 CYCLES_STATS_END(stacktrace_getClassContext)
995 return ca.get_handle();
999 /* stacktrace_getCurrentClass **************************************************
1001 Find the current class by walking the stack trace.
1003 Quote from the JNI documentation:
1005 In the Java 2 Platform, FindClass locates the class loader
1006 associated with the current native method. If the native code
1007 belongs to a system class, no class loader will be
1008 involved. Otherwise, the proper class loader will be invoked to
1009 load and link the named class. When FindClass is called through the
1010 Invocation Interface, there is no current native method or its
1011 associated class loader. In that case, the result of
1012 ClassLoader.getBaseClassLoader is used."
1014 *******************************************************************************/
1016 #if defined(ENABLE_JAVASE)
1017 classinfo *stacktrace_get_current_class(void)
1019 stackframeinfo_t *sfi;
1020 stackframeinfo_t tmpsfi;
1023 CYCLES_STATS_DECLARE_AND_START;
1025 #if !defined(NDEBUG)
1026 if (opt_DebugStackTrace)
1027 log_println("[stacktrace_get_current_class]");
1030 /* Get the stackframeinfo of the current thread. */
1032 sfi = threads_get_current_stackframeinfo();
1034 /* If the stackframeinfo is NULL then FindClass is called through
1035 the Invocation Interface and we return NULL */
1038 CYCLES_STATS_END(stacktrace_getCurrentClass);
1043 /* Iterate over the whole stack. */
1045 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1046 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1047 stacktrace_stackframeinfo_next(&tmpsfi)) {
1048 /* Get the methodinfo. */
1052 if (m->clazz == class_java_security_PrivilegedAction) {
1053 CYCLES_STATS_END(stacktrace_getCurrentClass);
1058 if (m->clazz != NULL) {
1059 CYCLES_STATS_END(stacktrace_getCurrentClass);
1065 /* No Java method found on the stack. */
1067 CYCLES_STATS_END(stacktrace_getCurrentClass);
1071 #endif /* ENABLE_JAVASE */
1074 /* stacktrace_get_stack ********************************************************
1076 Create a 2-dimensional array for java.security.VMAccessControler.
1080 NULL if an exception has been thrown
1082 *******************************************************************************/
1084 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1085 java_handle_objectarray_t *stacktrace_get_stack(void)
1087 stackframeinfo_t *sfi;
1088 stackframeinfo_t tmpsfi;
1091 java_handle_t *string;
1094 CYCLES_STATS_DECLARE_AND_START
1096 #if !defined(NDEBUG)
1097 if (opt_DebugStackTrace)
1098 log_println("[stacktrace_get_stack]");
1101 /* Get the stackframeinfo of the current thread. */
1103 sfi = threads_get_current_stackframeinfo();
1105 /* Get the depth of the current stack. */
1107 depth = stacktrace_depth(sfi);
1112 /* Allocate the required arrays. */
1114 ObjectArray oa(2, arrayclass_java_lang_Object);
1115 ClassArray classes(depth);
1116 ObjectArray methodnames(depth, class_java_lang_String);
1121 if (classes.is_null())
1124 if (methodnames.is_null())
1127 /* Set up the 2-dimensional array. */
1129 oa.set_element(0, (java_handle_t *) classes.get_handle());
1130 oa.set_element(1, (java_handle_t *) methodnames.get_handle());
1132 /* Iterate over the whole stack. */
1133 /* TODO We should use a critical section here to speed things
1138 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1139 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1140 stacktrace_stackframeinfo_next(&tmpsfi)) {
1141 /* Get the methodinfo. */
1145 /* Skip builtin methods. */
1147 if (m->flags & ACC_METHOD_BUILTIN)
1150 /* Store the class in the array. */
1152 classes.set_element(i, m->clazz);
1154 /* Store the name in the array. */
1156 string = javastring_new(m->name);
1161 methodnames.set_element(i, string);
1166 CYCLES_STATS_END(stacktrace_get_stack)
1168 return oa.get_handle();
1171 CYCLES_STATS_END(stacktrace_get_stack)
1178 /* stacktrace_print_entry ****************************************************
1180 Print line for a stacktrace entry.
1183 m ............ methodinfo of the entry
1184 linenumber ... linenumber of the entry
1186 *******************************************************************************/
1188 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1196 if (m->flags & ACC_METHOD_BUILTIN)
1199 utf_display_printable_ascii_classname(m->clazz->name);
1202 utf_display_printable_ascii(m->name);
1203 utf_display_printable_ascii(m->descriptor);
1205 if (m->flags & ACC_NATIVE) {
1206 puts("(Native Method)");
1209 if (m->flags & ACC_METHOD_BUILTIN) {
1214 utf_display_printable_ascii(m->clazz->sourcefile);
1215 printf(":%d)\n", linenumber);
1223 /* stacktrace_print ************************************************************
1225 Print the given stacktrace with CACAO intern methods only (no Java
1228 This method is used by stacktrace_dump_trace and
1229 builtin_trace_exception.
1232 st ... stacktrace to print
1234 *******************************************************************************/
1236 void stacktrace_print(stacktrace_t *st)
1238 stacktrace_entry_t *ste;
1243 ste = &(st->entries[0]);
1245 for (i = 0; i < st->length; i++, ste++) {
1248 /* Get the line number. */
1250 linenumber = ste->code->linenumbertable->find(&m, ste->pc);
1252 stacktrace_print_entry(m, linenumber);
1257 /* stacktrace_print_current ****************************************************
1259 Print the current stacktrace of the current thread.
1261 NOTE: This function prints all frames of the stacktrace and does
1262 not skip frames like stacktrace_get.
1264 *******************************************************************************/
1266 void stacktrace_print_current(void)
1268 stackframeinfo_t *sfi;
1269 stackframeinfo_t tmpsfi;
1274 sfi = threads_get_current_stackframeinfo();
1277 puts("\t<<No stacktrace available>>");
1282 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1283 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1284 stacktrace_stackframeinfo_next(&tmpsfi)) {
1285 /* Get the methodinfo. */
1290 // Get the line number.
1291 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1293 stacktrace_print_entry(m, linenumber);
1299 * Creates a stacktrace for the given thread.
1301 * @param t Given thread.
1302 * @return Current stacktrace of the given thread.
1304 * XXX: Creation of the stacktrace starts at the most recent
1305 * stackframeinfo block. If the thread is not inside the native
1306 * world, the created stacktrace is not complete!
1308 #if defined(ENABLE_THREADS)
1309 stacktrace_t* stacktrace_get_of_thread(threadobject* t)
1311 stackframeinfo_t* sfi;
1312 java_handle_bytearray_t* stba;
1315 sfi = t->_stackframeinfo;
1316 stba = stacktrace_get(sfi);
1323 st = (stacktrace_t*) ba.get_raw_data_ptr();
1330 /* stacktrace_print_of_thread **************************************************
1332 Print the current stacktrace of the given thread.
1337 *******************************************************************************/
1339 #if defined(ENABLE_THREADS)
1340 void stacktrace_print_of_thread(threadobject *t)
1342 stackframeinfo_t *sfi;
1343 stackframeinfo_t tmpsfi;
1348 /* Build a stacktrace for the passed thread. */
1350 sfi = t->_stackframeinfo;
1353 puts("\t<<No stacktrace available>>");
1358 for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1359 stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1360 stacktrace_stackframeinfo_next(&tmpsfi)) {
1361 /* Get the methodinfo. */
1366 // Get the line number.
1367 linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1369 stacktrace_print_entry(m, linenumber);
1375 /* stacktrace_print_exception **************************************************
1377 Print the stacktrace of a given exception (more or less a wrapper
1378 to stacktrace_print).
1381 h ... handle of exception to print
1383 *******************************************************************************/
1385 void stacktrace_print_exception(java_handle_t *h)
1390 java_lang_Throwable t(h);
1392 /* now print the stacktrace */
1394 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1396 java_lang_VMThrowable vmt(t.get_vmState());
1397 ByteArray backtrace(vmt.get_vmdata());
1399 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1401 ByteArray backtrace(t.get_backtrace());
1404 # error unknown classpath configuration
1409 assert(backtrace.is_non_null());
1411 /* We need a critical section here as we use the byte-array data
1412 pointer directly. */
1414 LLNI_CRITICAL_START;
1416 stacktrace_t* st = (stacktrace_t*) backtrace.get_raw_data_ptr();
1418 stacktrace_print(st);
1424 #if defined(ENABLE_CYCLES_STATS)
1425 void stacktrace_print_cycles_stats(FILE *file)
1427 CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1428 CYCLES_STATS_PRINT(stacktrace_get, file);
1429 CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1430 CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1431 CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1439 * These are local overrides for various environment variables in Emacs.
1440 * Please do not remove this and leave it at the end of the file, where
1441 * Emacs will automagically detect them.
1442 * ---------------------------------------------------------------------
1445 * indent-tabs-mode: t
1449 * vim:noexpandtab:sw=4:ts=4: