#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"
/* 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. */
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. */
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);
#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;
}
{
stacktracebuffer *stb;
stackframeinfo_t tmpsfi;
+ bool skip_fillInStackTrace;
+ bool skip_init;
+
+ skip_fillInStackTrace = true;
+ skip_init = true;
/* Create a stacktracebuffer in dump memory. */
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. */
}
#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 <init> methods of the exceptions klass. If there is
+ <init> 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) {