X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fstacktrace.c;h=b8847deb3ad31d9638d5ffd242b252900d2a8437;hb=caf4bfb972a703ceeaa4bdf5afb820bce15fd7e6;hp=d6b49cdf077aca7066a8a1db3ce29cfead807155;hpb=9ab52deb3ecafa51075dcbaeef4c5c50f6994965;p=cacao.git diff --git a/src/vm/jit/stacktrace.c b/src/vm/jit/stacktrace.c index d6b49cdf0..b8847deb3 100644 --- a/src/vm/jit/stacktrace.c +++ b/src/vm/jit/stacktrace.c @@ -65,6 +65,7 @@ #include "vm/jit/asmpart.h" #include "vm/jit/codegen-common.h" +#include "vm/jit/linenumbertable.h" #include "vm/jit/methodheader.h" #include "vmcore/class.h" @@ -333,7 +334,7 @@ static inline stacktracebuffer *stacktrace_method_add(stacktracebuffer *stb, sta /* Search the line number table. */ - linenumber = dseg_get_linenumber_from_pc(&m, pv, xpc); + linenumber = linenumbertable_linenumber_for_pc(&m, code, xpc); /* Add a new entry to the staktrace. */ @@ -348,26 +349,31 @@ static inline stacktracebuffer *stacktrace_method_add(stacktracebuffer *stb, sta Walk the stack (or the stackframeinfo-chain) to the next method. IN: - sfi....stackframeinfo of current method + tmpsfi ... stackframeinfo of current method + + RETURN: + true .... the sfi is filled with the new values + false ... we reached the top of the stacktrace *******************************************************************************/ -static inline void stacktrace_stack_walk(stackframeinfo_t *sfi) +static inline bool stacktrace_stack_walk(stackframeinfo_t *tmpsfi) { - codeinfo *code; - void *pv; - void *sp; - void *ra; - void *xpc; - uint32_t framesize; + codeinfo *code; + void *pv; + void *sp; + void *ra; + void *xpc; + uint32_t framesize; + stackframeinfo_t *prevsfi; /* Get values from the stackframeinfo. */ - code = sfi->code; - pv = sfi->pv; - sp = sfi->sp; - ra = sfi->ra; - xpc = sfi->xpc; + code = tmpsfi->code; + pv = tmpsfi->pv; + sp = tmpsfi->sp; + ra = tmpsfi->ra; + xpc = tmpsfi->xpc; /* Get the current stack frame size. */ @@ -385,14 +391,8 @@ static inline void stacktrace_stack_walk(stackframeinfo_t *sfi) else # endif { - /* TODO Remove jd->isleafmethod and use the flags in - codeinfo. */ - -/* if (!CODE_IS_LEAFMETHOD(m->code)) { */ - int32_t isleafmethod = *((int32_t *) (((intptr_t) pv) + IsLeaf)); - if (!isleafmethod) { + if (!code_is_leafmethod(code)) ra = md_stacktrace_get_returnaddress(sp, framesize); - } } #else ra = intrp_md_stacktrace_get_returnaddress(sp, framesize); @@ -437,15 +437,46 @@ static inline void stacktrace_stack_walk(stackframeinfo_t *sfi) #endif } - /* Store the new values in the stackframeinfo. NOTE: We subtract - 1 from the RA to get the XPC, because the RA points to the - instruction after the call instruction. */ + /* If the new codeinfo pointer is NULL we reached a + asm_vm_call_method function. In this case we get the next + values from the previous stackframeinfo in the chain. + Otherwise the new values have been calculated before. */ - sfi->code = code; - sfi->pv = pv; - sfi->sp = sp; - sfi->ra = ra; - sfi->xpc = (void *) (((intptr_t) ra) - 1); + if (code == NULL) { + prevsfi = tmpsfi->prev; + + /* If the previous stackframeinfo in the chain is NULL we + reached the top of the stacktrace and return false. */ + + if (prevsfi == NULL) + return false; + + /* Fill the temporary stackframeinfo with the new values. */ + + tmpsfi->code = prevsfi->code; + tmpsfi->pv = prevsfi->pv; + tmpsfi->sp = prevsfi->sp; + tmpsfi->ra = prevsfi->ra; + tmpsfi->xpc = prevsfi->xpc; + + /* Set the previous stackframe info of the temporary one to + the next in the chain. */ + + tmpsfi->prev = prevsfi->prev; + } + else { + /* Store the new values in the stackframeinfo. NOTE: We + subtract 1 from the RA to get the XPC, because the RA + points to the instruction after the call instruction. */ + + tmpsfi->code = code; + tmpsfi->pv = pv; + tmpsfi->sp = sp; + tmpsfi->ra = ra; + tmpsfi->xpc = (void *) (((intptr_t) ra) - 1); + } + + return true; } @@ -470,6 +501,11 @@ stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi) { stacktracebuffer *stb; stackframeinfo_t tmpsfi; + bool skip_fillInStackTrace; + bool skip_init; + + skip_fillInStackTrace = true; + skip_init = true; /* Create a stacktracebuffer in dump memory. */ @@ -499,9 +535,14 @@ stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi) tmpsfi.ra = sfi->ra; tmpsfi.xpc = sfi->xpc; + /* Initially set the previous stackframe info of the temporary one + to the next in the chain. */ + + tmpsfi.prev = sfi->prev; + /* Iterate till we're done. */ - for (;;) { + do { #if !defined(NDEBUG) /* Print current method information. */ @@ -516,45 +557,50 @@ stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi) } #endif - /* Check for Throwable.fillInStackTrace(). */ + /* This logic is taken from + hotspot/src/share/vm/classfile/javaClasses.cpp + (java_lang_Throwable::fill_in_stack_trace). */ -/* if (tmpsfi.method->name != utf_fillInStackTrace) { */ - - /* Add this method to the stacktrace. */ + if (skip_fillInStackTrace == true) { + /* Check "fillInStackTrace" only once, so we negate the + flag after the first time check. */ - stb = stacktrace_method_add(stb, &tmpsfi); -/* } */ +#if defined(WITH_CLASSPATH_GNU) + /* For GNU Classpath we also need to skip + VMThrowable.fillInStackTrace(). */ - /* Walk the stack (or the stackframeinfo chain) and get the - next method. */ + if ((tmpsfi.code->m->class == class_java_lang_VMThrowable) && + (tmpsfi.code->m->name == utf_fillInStackTrace)) + continue; +#endif - stacktrace_stack_walk(&tmpsfi); + skip_fillInStackTrace = false; - /* If the new codeinfo pointer is NULL we reached a - asm_vm_call_method function. In this case we get the next - values from the previous stackframeinfo in the chain. - Otherwise the new values have been calculated before. */ + if (tmpsfi.code->m->name == utf_fillInStackTrace) + continue; + } - if (tmpsfi.code == NULL) { - sfi = sfi->prev; + /* Skip methods of the exceptions klass. If there is + methods that belongs to a superclass of the + exception we are going to skipping them in stack trace. */ - /* If the previous stackframeinfo in the chain is NULL we - reached the top of the stacktrace and leave the - loop. */ + if (skip_init == true) { + if (tmpsfi.code->m->name == utf_init) { +/* throwable->is_a(method->method_holder())) { */ + continue; + } + else { + /* If no "Throwable.init()" method found, we stop + checking it next time. */ - if (sfi == NULL) - break; + skip_init = false; + } + } - /* Fill the temporary stackframeinfo with the new - values. */ + /* Add this method to the stacktrace. */ - tmpsfi.code = sfi->code; - tmpsfi.pv = sfi->pv; - tmpsfi.sp = sfi->sp; - tmpsfi.ra = sfi->ra; - tmpsfi.xpc = sfi->xpc; - } - } + stb = stacktrace_method_add(stb, &tmpsfi); + } while (stacktrace_stack_walk(&tmpsfi) == true); #if !defined(NDEBUG) if (opt_DebugStackTrace) {