X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fvm%2Fjit%2Fstacktrace.c;h=461c09d18f68d38ff92196ac1ad0f2daf64febab;hb=8c81647e1c96715f45498a3ada7f795b5c9dfe81;hp=e8d59d422a513669569c4c0aa59304362eb4cdbd;hpb=33db9dba97d8dc53e034b8720443c075546d8b03;p=cacao.git diff --git a/src/vm/jit/stacktrace.c b/src/vm/jit/stacktrace.c index e8d59d422..461c09d18 100644 --- a/src/vm/jit/stacktrace.c +++ b/src/vm/jit/stacktrace.c @@ -1,9 +1,7 @@ /* src/vm/jit/stacktrace.c - machine independent stacktrace system - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -44,17 +42,16 @@ #include "vm/global.h" /* required here for native includes */ #include "native/jni.h" #include "native/llni.h" + +#include "native/include/java_lang_Object.h" #include "native/include/java_lang_Throwable.h" #if defined(WITH_CLASSPATH_GNU) +# include "native/include/gnu_classpath_Pointer.h" # include "native/include/java_lang_VMThrowable.h" #endif -#if defined(ENABLE_THREADS) -# include "threads/native/threads.h" -#else -# include "threads/none/threads.h" -#endif +#include "threads/thread.h" #include "toolbox/logging.h" @@ -69,16 +66,15 @@ #include "vm/jit/codegen-common.h" #include "vm/jit/linenumbertable.h" #include "vm/jit/methodheader.h" +#include "vm/jit/methodtree.h" #include "vmcore/class.h" #include "vmcore/loader.h" +#include "vmcore/method.h" #include "vmcore/options.h" /* global variables ***********************************************************/ -#if !defined(ENABLE_THREADS) -stackframeinfo_t *_no_threads_stackframeinfo = NULL; -#endif CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1) CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000) @@ -97,18 +93,15 @@ CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000) void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc) { - stackframeinfo_t **psfi; - codeinfo *code; -#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__) - bool isleafmethod; -#endif + stackframeinfo_t *currentsfi; + codeinfo *code; #if defined(ENABLE_JIT) s4 framesize; #endif - /* get current stackframe info pointer */ + /* Get current stackframe info. */ - psfi = &STACKFRAMEINFO; + currentsfi = threads_get_current_stackframeinfo(); /* sometimes we don't have pv handy (e.g. in asmpart.S: L_asm_call_jit_compiler_exception or in the interpreter). */ @@ -116,7 +109,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra if (pv == NULL) { #if defined(ENABLE_INTRP) if (opt_intrp) - pv = codegen_get_pv_from_pc(ra); + pv = methodtree_find(ra); else #endif { @@ -135,7 +128,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra code = code_get_codeinfo_for_pv(pv); /* XXX */ -/* assert(m != NULL); */ + /* assert(m != NULL); */ #if defined(ENABLE_JIT) # if defined(ENABLE_INTRP) @@ -154,14 +147,13 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra ra = md_stacktrace_get_returnaddress(sp, framesize); # else - /* If the method is a non-leaf function, we need to get the return - address from the stack. For leaf functions the return address - is set correctly. This makes the assembler and the signal - handler code simpler. */ - - isleafmethod = *((s4 *) (pv + IsLeaf)); + /* If the method is a non-leaf function, we need to get the + return address from the stack. For leaf functions the + return address is set correctly. This makes the assembler + and the signal handler code simpler. The code is NULL is + the asm_vm_call_method special case. */ - if (!isleafmethod) { + if ((code == NULL) || !code_is_leafmethod(code)) { framesize = *((u4 *) (pv + FrameSize)); ra = md_stacktrace_get_returnaddress(sp, framesize); @@ -183,7 +175,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra /* Fill new stackframeinfo structure. */ - sfi->prev = *psfi; + sfi->prev = currentsfi; sfi->code = code; sfi->pv = pv; sfi->sp = sp; @@ -203,7 +195,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra /* Store new stackframeinfo pointer. */ - *psfi = sfi; + threads_set_current_stackframeinfo(sfi); /* set the native world flag for the current thread */ /* ATTENTION: This flag tells the GC how to treat this thread in case of @@ -222,17 +214,11 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi) { - stackframeinfo_t **psfi; - - /* clear the native world flag for the current thread */ - /* ATTENTION: Clear this flag _before_ removing the stackframe info */ + /* Clear the native world flag for the current thread. */ + /* ATTENTION: Clear this flag _before_ removing the stackframe info. */ THREAD_NATIVEWORLD_EXIT; - /* get current stackframe info pointer */ - - psfi = &STACKFRAMEINFO; - #if !defined(NDEBUG) if (opt_DebugStackFrameInfo) { log_start(); @@ -244,9 +230,9 @@ void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi) } #endif - /* restore the old pointer */ + /* Set previous stackframe info. */ - *psfi = sfi->prev; + threads_set_current_stackframeinfo(sfi->prev); } @@ -282,18 +268,8 @@ static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stac tmpsfi->prev = sfi->prev; #if !defined(NDEBUG) - /* Print current method information. */ - - if (opt_DebugStackTrace) { - log_println("[stacktrace start]"); - log_start(); - log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=", - tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra, - tmpsfi->xpc); - method_print(tmpsfi->code->m); - log_print("]"); - log_finish(); - } + if (opt_DebugStackTrace) + log_println("[stacktrace fill]"); #endif } @@ -360,7 +336,7 @@ static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi) #if defined(ENABLE_INTRP) if (opt_intrp) - pv = codegen_get_pv_from_pc(ra); + pv = methodtree_find(ra); else #endif { @@ -532,18 +508,20 @@ static int stacktrace_depth(stackframeinfo_t *sfi) /* stacktrace_get ************************************************************** - Builds and returns a stacktrace from the current thread for and - returns the stacktrace structure wrapped in a Java byte-array to - not confuse the GC. + Builds and returns a stacktrace starting from the given stackframe + info and returns the stacktrace structure wrapped in a Java + byte-array to not confuse the GC. + + IN: + sfi ... stackframe info to start stacktrace from RETURN: stacktrace as Java byte-array *******************************************************************************/ -java_handle_bytearray_t *stacktrace_get(void) +java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi) { - stackframeinfo_t *sfi; stackframeinfo_t tmpsfi; int depth; java_handle_bytearray_t *ba; @@ -564,10 +542,6 @@ java_handle_bytearray_t *stacktrace_get(void) skip_fillInStackTrace = true; skip_init = true; - /* Get the stacktrace depth of the current thread. */ - - sfi = STACKFRAMEINFO; - depth = stacktrace_depth(sfi); if (depth == 0) @@ -623,7 +597,7 @@ java_handle_bytearray_t *stacktrace_get(void) /* For GNU Classpath we also need to skip VMThrowable.fillInStackTrace(). */ - if ((m->class == class_java_lang_VMThrowable) && + if ((m->clazz == class_java_lang_VMThrowable) && (m->name == utf_fillInStackTrace)) continue; #endif @@ -639,8 +613,8 @@ java_handle_bytearray_t *stacktrace_get(void) exception we are going to skipping them in stack trace. */ if (skip_init == true) { - if (m->name == utf_init) { -/* throwable->is_a(method->method_holder())) { */ + if ((m->name == utf_init) && + (class_issubclass(m->clazz, class_java_lang_Throwable))) { continue; } else { @@ -683,6 +657,105 @@ return_NULL: } +/* stacktrace_get_current ****************************************************** + + Builds and returns a stacktrace from the current thread and returns + the stacktrace structure wrapped in a Java byte-array to not + confuse the GC. + + RETURN: + stacktrace as Java byte-array + +*******************************************************************************/ + +java_handle_bytearray_t *stacktrace_get_current(void) +{ + stackframeinfo_t *sfi; + java_handle_bytearray_t *ba; + + sfi = threads_get_current_stackframeinfo(); + ba = stacktrace_get(sfi); + + return ba; +} + + +/* stacktrace_get_caller_class ************************************************* + + Get the class on the stack at the given depth. This function skips + various special classes or methods. + + ARGUMENTS: + depth ... depth to get caller class of + + RETURN: + caller class + +*******************************************************************************/ + +#if defined(ENABLE_JAVASE) +classinfo *stacktrace_get_caller_class(int depth) +{ + stackframeinfo_t *sfi; + stackframeinfo_t tmpsfi; + methodinfo *m; + classinfo *c; + int i; + +#if !defined(NDEBUG) + if (opt_DebugStackTrace) + log_println("[stacktrace_get_caller_class]"); +#endif + + /* Get the stackframeinfo of the current thread. */ + + sfi = threads_get_current_stackframeinfo(); + + /* Iterate over the whole stack until we reached the requested + depth. */ + + i = 0; + + for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi); + stacktrace_stackframeinfo_end_check(&tmpsfi) == false; + stacktrace_stackframeinfo_next(&tmpsfi)) { + + m = tmpsfi.code->m; + c = m->clazz; + + /* Skip builtin methods. */ + + if (m->flags & ACC_METHOD_BUILTIN) + continue; + +#if defined(WITH_CLASSPATH_SUN) + /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp + (vframeStreamCommon::security_get_caller_frame). */ + + /* This is java.lang.reflect.Method.invoke(), skip it. */ + + if (m == method_java_lang_reflect_Method_invoke) + continue; + + /* This is an auxiliary frame, skip it. */ + + if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl)) + continue; +#endif + + /* We reached the requested depth. */ + + if (i >= depth) + return c; + + i++; + } + + return NULL; +} +#endif + + /* stacktrace_first_nonnull_classloader **************************************** Returns the first non-null (user-defined) classloader on the stack. @@ -693,12 +766,12 @@ return_NULL: *******************************************************************************/ -classloader *stacktrace_first_nonnull_classloader(void) +classloader_t *stacktrace_first_nonnull_classloader(void) { stackframeinfo_t *sfi; stackframeinfo_t tmpsfi; methodinfo *m; - classloader *cl; + classloader_t *cl; #if !defined(NDEBUG) if (opt_DebugStackTrace) @@ -707,7 +780,7 @@ classloader *stacktrace_first_nonnull_classloader(void) /* Get the stackframeinfo of the current thread. */ - sfi = STACKFRAMEINFO; + sfi = threads_get_current_stackframeinfo(); /* Iterate over the whole stack. */ @@ -716,7 +789,7 @@ classloader *stacktrace_first_nonnull_classloader(void) stacktrace_stackframeinfo_next(&tmpsfi)) { m = tmpsfi.code->m; - cl = class_get_classloader(m->class); + cl = class_get_classloader(m->clazz); if (cl != NULL) return cl; @@ -753,7 +826,7 @@ java_handle_objectarray_t *stacktrace_getClassContext(void) log_println("[stacktrace_getClassContext]"); #endif - sfi = STACKFRAMEINFO; + sfi = threads_get_current_stackframeinfo(); /* Get the depth of the current stack. */ @@ -801,7 +874,7 @@ java_handle_objectarray_t *stacktrace_getClassContext(void) /* Store the class in the array. */ - data[i] = (java_object_t *) m->class; + data[i] = (java_object_t *) m->clazz; i++; } @@ -847,7 +920,7 @@ classinfo *stacktrace_get_current_class(void) /* Get the stackframeinfo of the current thread. */ - sfi = STACKFRAMEINFO; + sfi = threads_get_current_stackframeinfo(); /* If the stackframeinfo is NULL then FindClass is called through the Invocation Interface and we return NULL */ @@ -867,16 +940,16 @@ classinfo *stacktrace_get_current_class(void) m = tmpsfi.code->m; - if (m->class == class_java_security_PrivilegedAction) { + if (m->clazz == class_java_security_PrivilegedAction) { CYCLES_STATS_END(stacktrace_getCurrentClass); return NULL; } - if (m->class != NULL) { + if (m->clazz != NULL) { CYCLES_STATS_END(stacktrace_getCurrentClass); - return m->class; + return m->clazz; } } @@ -921,7 +994,7 @@ java_handle_objectarray_t *stacktrace_get_stack(void) /* Get the stackframeinfo of the current thread. */ - sfi = STACKFRAMEINFO; + sfi = threads_get_current_stackframeinfo(); /* Get the depth of the current stack. */ @@ -974,7 +1047,7 @@ java_handle_objectarray_t *stacktrace_get_stack(void) /* NOTE: We use a LLNI-macro here, because a classinfo is not a handle. */ - LLNI_array_direct(classes, i) = (java_object_t *) m->class; + LLNI_array_direct(classes, i) = (java_object_t *) m->clazz; /* Store the name in the array. */ @@ -1000,6 +1073,51 @@ return_NULL: #endif +/* stacktrace_print_entry **************************************************** + + Print line for a stacktrace entry. + + ARGUMENTS: + m ............ methodinfo of the entry + linenumber ... linenumber of the entry + +*******************************************************************************/ + +static void stacktrace_print_entry(methodinfo *m, int32_t linenumber) +{ + /* Sanity check. */ + + assert(m != NULL); + + printf("\tat "); + + if (m->flags & ACC_METHOD_BUILTIN) + printf("NULL"); + else + utf_display_printable_ascii_classname(m->clazz->name); + + printf("."); + utf_display_printable_ascii(m->name); + utf_display_printable_ascii(m->descriptor); + + if (m->flags & ACC_NATIVE) { + puts("(Native Method)"); + } + else { + if (m->flags & ACC_METHOD_BUILTIN) { + puts("(builtin)"); + } + else { + printf("("); + utf_display_printable_ascii(m->clazz->sourcefile); + printf(":%d)\n", linenumber); + } + } + + fflush(stdout); +} + + /* stacktrace_print ************************************************************ Print the given stacktrace with CACAO intern methods only (no Java @@ -1029,28 +1147,99 @@ void stacktrace_print(stacktrace_t *st) linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc); - printf("\tat "); - utf_display_printable_ascii_classname(m->class->name); - printf("."); - utf_display_printable_ascii(m->name); - utf_display_printable_ascii(m->descriptor); + stacktrace_print_entry(m, linenumber); + } +} - if (m->flags & ACC_NATIVE) { - puts("(Native Method)"); - } - else { - printf("("); - utf_display_printable_ascii(m->class->sourcefile); - printf(":%d)\n", linenumber); - } + +/* stacktrace_print_current **************************************************** + + Print the current stacktrace of the current thread. + + NOTE: This function prints all frames of the stacktrace and does + not skip frames like stacktrace_get. + +*******************************************************************************/ + +void stacktrace_print_current(void) +{ + stackframeinfo_t *sfi; + stackframeinfo_t tmpsfi; + codeinfo *code; + methodinfo *m; + int32_t linenumber; + + sfi = threads_get_current_stackframeinfo(); + + if (sfi == NULL) { + puts("\t<>"); + fflush(stdout); + return; } - /* just to be sure */ + for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi); + stacktrace_stackframeinfo_end_check(&tmpsfi) == false; + stacktrace_stackframeinfo_next(&tmpsfi)) { + /* Get the methodinfo. */ + + code = tmpsfi.code; + m = code->m; - fflush(stdout); + /* Get the line number. */ + + linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc); + + stacktrace_print_entry(m, linenumber); + } } +/* stacktrace_print_of_thread ************************************************** + + Print the current stacktrace of the given thread. + + ARGUMENTS: + t ... thread + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) +void stacktrace_print_of_thread(threadobject *t) +{ + stackframeinfo_t *sfi; + stackframeinfo_t tmpsfi; + codeinfo *code; + methodinfo *m; + int32_t linenumber; + + /* Build a stacktrace for the passed thread. */ + + sfi = t->_stackframeinfo; + + if (sfi == NULL) { + puts("\t<>"); + fflush(stdout); + return; + } + + for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi); + stacktrace_stackframeinfo_end_check(&tmpsfi) == false; + stacktrace_stackframeinfo_next(&tmpsfi)) { + /* Get the methodinfo. */ + + code = tmpsfi.code; + m = code->m; + + /* Get the line number. */ + + linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc); + + stacktrace_print_entry(m, linenumber); + } +} +#endif + + /* stacktrace_print_exception ************************************************** Print the stacktrace of a given exception (more or less a wrapper @@ -1064,9 +1253,12 @@ void stacktrace_print(stacktrace_t *st) void stacktrace_print_exception(java_handle_t *h) { java_lang_Throwable *o; + #if defined(WITH_CLASSPATH_GNU) java_lang_VMThrowable *vmt; #endif + + java_lang_Object *backtrace; java_handle_bytearray_t *ba; stacktrace_t *st; @@ -1080,16 +1272,18 @@ void stacktrace_print_exception(java_handle_t *h) #if defined(WITH_CLASSPATH_GNU) LLNI_field_get_ref(o, vmState, vmt); - LLNI_field_get_ref(vmt, vmData, ba); + LLNI_field_get_ref(vmt, vmdata, backtrace); #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1) - LLNI_field_get_ref(o, backtrace, ba); + LLNI_field_get_ref(o, backtrace, backtrace); #else # error unknown classpath configuration #endif + ba = (java_handle_bytearray_t *) backtrace; + /* Sanity check. */ assert(ba != NULL);