#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "toolbox/logging.h"
+#include "vm/array.h"
#include "vm/builtin.h"
#include "vm/cycles-stats.h"
#include "vm/exceptions.h"
#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"
/* global variables ***********************************************************/
#if !defined(ENABLE_THREADS)
-stackframeinfo *_no_threads_stackframeinfo = NULL;
+stackframeinfo_t *_no_threads_stackframeinfo = NULL;
#endif
CYCLES_STATS_DECLARE(stacktrace_overhead ,100,1)
CYCLES_STATS_DECLARE(stacktrace_getStack ,40,10000)
-/* stacktrace_create_stackframeinfo ********************************************
+/* stacktrace_stackframeinfo_add ***********************************************
- Creates an stackframe info structure for inline code in the
- interpreter.
+ Fills a stackframe info structure with the given or calculated
+ values and adds it to the chain.
*******************************************************************************/
-#if defined(ENABLE_INTRP)
-void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
- u1 *ra)
+void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
{
- stackframeinfo **psfi;
- methodinfo *m;
- codeinfo *code;
-
- /* get current stackframe info pointer */
-
- psfi = &STACKFRAMEINFO;
-
- /* if we don't have pv handy */
-
- if (pv == NULL) {
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- pv = codegen_get_pv_from_pc(ra);
- else
-#endif
- {
-#if defined(ENABLE_JIT)
- pv = md_codegen_get_pv_from_pc(ra);
-#endif
- }
- }
-
- /* get codeinfo pointer from data segment */
-
- code = *((codeinfo **) (pv + CodeinfoPointer));
-
- /* For asm_vm_call_method the codeinfo pointer is NULL. */
-
- m = (code == NULL) ? NULL : code->m;
-
- /* fill new stackframe info structure */
-
- sfi->prev = *psfi;
- sfi->method = m;
- sfi->pv = pv;
- sfi->sp = sp;
- sfi->ra = ra;
-
- /* xpc is the same as ra, but is required in stacktrace_create */
-
- sfi->xpc = ra;
-
- /* store new stackframe info pointer */
-
- *psfi = sfi;
-}
-#endif /* defined(ENABLE_INTRP) */
-
-
-/* stacktrace_create_extern_stackframeinfo *************************************
-
- Creates an stackframe info structure for an extern exception
- (hardware or assembler).
-
-*******************************************************************************/
-
-void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
- u1 *sp, u1 *ra, u1 *xpc)
-{
- stackframeinfo **psfi;
+ stackframeinfo_t **psfi;
+ codeinfo *code;
#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
- bool isleafmethod;
+ bool isleafmethod;
#endif
#if defined(ENABLE_JIT)
- s4 framesize;
+ s4 framesize;
#endif
/* get current stackframe info pointer */
}
}
+ /* Get codeinfo pointer for the parent Java method. */
+
+ code = code_get_codeinfo_for_pv(pv);
+
+ /* XXX */
+/* assert(m != NULL); */
+
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
/* When using the interpreter, we pass RA to the function. */
# if defined(ENABLE_INTRP)
}
# endif
-#endif /* defined(ENABLE_JIT) */
-
- /* fill new stackframe info structure */
-
- sfi->prev = *psfi;
- sfi->method = NULL;
- sfi->pv = pv;
- sfi->sp = sp;
- sfi->ra = ra;
- sfi->xpc = xpc;
-
- /* store new stackframe info pointer */
-
- *psfi = sfi;
-
- /* set the native world flag for the current thread */
- /* ATTENTION: This flag tells the GC how to treat this thread in case of
- a collection. Set this flag _after_ a valid stackframe info was set. */
-
- THREAD_NATIVEWORLD_ENTER;
-}
-
-
-/* stacktrace_create_native_stackframeinfo *************************************
-
- Creates a stackframe info structure for a native stub.
-
-*******************************************************************************/
-
-void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
- u1 *sp, u1 *ra)
-{
- stackframeinfo **psfi;
- methodinfo *m;
- codeinfo *code;
-
- /* get codeinfo pointer from data segment */
-
- code = *((codeinfo **) (pv + CodeinfoPointer));
-
- /* For asm_vm_call_method the codeinfo pointer is NULL. */
+#endif
- m = (code == NULL) ? NULL : code->m;
+ /* Calculate XPC when not given. The XPC is then the return
+ address of the current method minus 1 because the RA points to
+ the instruction after the call instruction. This is required
+ e.g. for method stubs. */
- /* get current stackframe info pointer */
+ if (xpc == NULL) {
+ xpc = (void *) (((intptr_t) ra) - 1);
+ }
- psfi = &STACKFRAMEINFO;
+ /* Fill new stackframeinfo structure. */
- /* fill new stackframe info structure */
+ sfi->prev = *psfi;
+ sfi->code = code;
+ sfi->pv = pv;
+ sfi->sp = sp;
+ sfi->ra = ra;
+ sfi->xpc = xpc;
- sfi->prev = *psfi;
- sfi->method = m;
- sfi->pv = NULL;
- sfi->sp = sp;
- sfi->ra = ra;
- sfi->xpc = NULL;
+#if !defined(NDEBUG)
+ if (opt_DebugStackFrameInfo) {
+ log_start();
+ log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+ sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
+ method_print(sfi->code->m);
+ log_print("]");
+ log_finish();
+ }
+#endif
- /* store new stackframe info pointer */
+ /* Store new stackframeinfo pointer. */
*psfi = sfi;
}
-/* stacktrace_remove_stackframeinfo ********************************************
+/* stacktrace_stackframeinfo_remove ********************************************
- Remove the topmost stackframeinfo in the current thread.
+ Remove the given stackframeinfo from the chain in the current
+ thread.
*******************************************************************************/
-void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
+void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
{
- stackframeinfo **psfi;
+ stackframeinfo_t **psfi;
/* clear the native world flag for the current thread */
/* ATTENTION: Clear this flag _before_ removing the stackframe info */
psfi = &STACKFRAMEINFO;
+#if !defined(NDEBUG)
+ if (opt_DebugStackFrameInfo) {
+ log_start();
+ log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+ sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
+ method_print(sfi->code->m);
+ log_print("]");
+ log_finish();
+ }
+#endif
+
/* restore the old pointer */
*psfi = sfi->prev;
}
-/* stacktrace_add_entry ********************************************************
+/* stacktrace_entry_add ********************************************************
Adds a new entry to the stacktrace buffer.
*******************************************************************************/
-static stacktracebuffer *stacktrace_add_entry(stacktracebuffer *stb,
- methodinfo *m, u2 line)
+static inline stacktracebuffer *stacktrace_entry_add(stacktracebuffer *stb, methodinfo *m, u2 line)
{
stacktrace_entry *ste;
u4 stb_size_old;
}
-/* stacktrace_add_method *******************************************************
+/* stacktrace_method_add *******************************************************
- Add stacktrace entries[1] for the given method to the stacktrace buffer.
+ Add stacktrace entries[1] for the given method to the stacktrace
+ buffer.
IN:
- stb.........stacktracebuffer to fill
- m...........method for which entries should be created
- pv..........pv of method
- pc..........position of program counter within the method's code
-
+ stb....stacktracebuffer to fill
+ sfi....current stackframeinfo
OUT:
stacktracebuffer after possible reallocation.
*******************************************************************************/
-static stacktracebuffer *stacktrace_add_method(stacktracebuffer *stb,
- methodinfo *m, u1 *pv, u1 *pc)
+static inline stacktracebuffer *stacktrace_method_add(stacktracebuffer *stb, stackframeinfo_t *sfi)
{
- codeinfo *code; /* compiled realization of method */
- s4 linenumber;
+ codeinfo *code;
+ void *pv;
+ void *xpc;
+ methodinfo *m;
+ int32_t linenumber;
+
+ /* Get values from the stackframeinfo. */
- /* find the realization of the method the pc is in */
+ code = sfi->code;
+ pv = sfi->pv;
+ xpc = sfi->xpc;
- code = *((codeinfo **) (pv + CodeinfoPointer));
+ m = code->m;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ return stb;
- /* search the line number table */
+ /* Search the line number table. */
- linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, xpc);
- /* now add a new entry to the staktrace */
+ /* Add a new entry to the staktrace. */
- stb = stacktrace_add_entry(stb, m, linenumber);
+ stb = stacktrace_entry_add(stb, m, linenumber);
return stb;
}
-/* stacktrace_create ***********************************************************
+/* stacktrace_stack_walk *******************************************************
- Generates a stacktrace from the thread passed into a
- stacktracebuffer. The stacktracebuffer is allocated on the
- dump memory.
-
- NOTE: The first element in the stackframe chain must always be a
- native stackframeinfo (e.g. VMThrowable.fillInStackTrace() is
- a native function).
+ Walk the stack (or the stackframeinfo-chain) to the next method.
- RETURN VALUE:
- pointer to the stacktracebuffer, or
- NULL if there is no stacktrace available for the
- given thread.
+ IN:
+ tmpsfi ... stackframeinfo of current method
+
+ RETURN:
+ true .... the sfi is filled with the new values
+ false ... we reached the top of the stacktrace
*******************************************************************************/
-stacktracebuffer *stacktrace_create(stackframeinfo *sfi)
+static inline bool stacktrace_stack_walk(stackframeinfo_t *tmpsfi)
{
- stacktracebuffer *stb;
- methodinfo *m;
codeinfo *code;
- u1 *pv;
- u1 *sp;
- u4 framesize;
- u1 *ra;
- u1 *xpc;
+ void *pv;
+ void *sp;
+ void *ra;
+ void *xpc;
+ uint32_t framesize;
+ stackframeinfo_t *prevsfi;
- /* prevent compiler warnings */
+ /* Get values from the stackframeinfo. */
- pv = NULL;
- sp = NULL;
- ra = NULL;
+ code = tmpsfi->code;
+ pv = tmpsfi->pv;
+ sp = tmpsfi->sp;
+ ra = tmpsfi->ra;
+ xpc = tmpsfi->xpc;
- /* create a stacktracebuffer in dump memory */
+ /* Get the current stack frame size. */
- stb = DNEW(stacktracebuffer);
+ framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
- stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
- stb->used = 0;
+ /* Get the RA of the current stack frame (RA to the parent Java
+ method) if the current method is a non-leaf method. Otherwise
+ the value in the stackframeinfo is correct (from the signal
+ handler). */
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf("\n\n---> stacktrace creation start (fillInStackTrace):\n");
- fflush(stdout);
- }
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
+ else
+# endif
+ {
+ if (!code_is_leafmethod(code))
+ ra = md_stacktrace_get_returnaddress(sp, framesize);
+ }
+#else
+ ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
#endif
- /* Loop while we have a method pointer (asm_calljavafunction has
- NULL) or there is a stackframeinfo in the chain. */
-
- m = NULL;
-
- while ((m != NULL) || (sfi != NULL)) {
- /* m == NULL should only happen for the first time and inline
- stackframe infos, like from the exception stubs or the
- patcher wrapper. */
-
- if (m == NULL) {
- /* for native stub stackframe infos, pv is always NULL */
-
- if (sfi->pv == NULL) {
- /* get methodinfo, sp and ra from the current stackframe info */
-
- m = sfi->method;
- sp = sfi->sp; /* sp of parent Java function */
- ra = sfi->ra;
-
- if (m && !(m->flags & ACC_METHOD_BUILTIN))
- stb = stacktrace_add_entry(stb, m, 0);
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf("ra=%p sp=%p, ", ra, sp);
- method_print(m);
- if (m)
- printf(": native stub\n");
- else
- printf(": builtin stub\n");
- fflush(stdout);
- }
-#endif
- /* This is an native stub stackframe info, so we can
- get the parent pv from the return address
- (ICMD_INVOKE*). */
+ /* Get the PV for the parent Java method. */
#if defined(ENABLE_INTRP)
- if (opt_intrp)
- pv = codegen_get_pv_from_pc(ra);
- else
+ if (opt_intrp)
+ pv = codegen_get_pv_from_pc(ra);
+ else
#endif
- {
+ {
#if defined(ENABLE_JIT)
- pv = md_codegen_get_pv_from_pc(ra);
+# if defined(__SPARC_64__)
+ sp = md_get_framepointer(sp);
+ pv = md_get_pv_from_stackframe(sp);
+# else
+ pv = md_codegen_get_pv_from_pc(ra);
+# endif
#endif
- }
-
- /* get methodinfo pointer from parent data segment */
-
- code = *((codeinfo **) (pv + CodeinfoPointer));
-
- /* For asm_vm_call_method the codeinfo pointer is
- NULL. */
-
- m = (code == NULL) ? NULL : code->m;
+ }
- } else {
- /* Inline stackframe infos are special: they have a
- xpc of the actual exception position and the return
- address saved since an inline stackframe info can
- also be in a leaf method (no return address saved
- on stack!!!). ATTENTION: This one is also for
- hardware exceptions!!! */
+ /* Get the codeinfo pointer for the parent Java method. */
- /* get methodinfo, sp and ra from the current stackframe info */
+ code = code_get_codeinfo_for_pv(pv);
- m = sfi->method; /* m == NULL */
- pv = sfi->pv; /* pv of parent Java function */
- sp = sfi->sp; /* sp of parent Java function */
- ra = sfi->ra; /* ra of parent Java function */
- xpc = sfi->xpc; /* actual exception position */
+ /* Calculate the SP for the parent Java method. */
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf("ra=%p sp=%p, ", ra, sp);
- printf("NULL: extern stackframe\n");
- fflush(stdout);
- }
+#if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ sp = *(u1 **) (sp - framesize);
+ else
#endif
+ {
+#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
+ sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
+#elif defined(__SPARC_64__)
+ /* already has the new sp */
+#else
+ sp = (void *) (((intptr_t) sp) + framesize);
+#endif
+ }
- /* get methodinfo from current Java method */
+ /* 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. */
- code = *((codeinfo **) (pv + CodeinfoPointer));
+ if (code == NULL) {
+ prevsfi = tmpsfi->prev;
- /* For asm_vm_call_method the codeinfo pointer is
- NULL. */
+ /* If the previous stackframeinfo in the chain is NULL we
+ reached the top of the stacktrace and return false. */
- m = (code == NULL) ? NULL : code->m;
+ if (prevsfi == NULL)
+ return false;
- /* if m == NULL, this is a asm_calljavafunction call */
+ /* Fill the temporary stackframeinfo with the new values. */
- if (m != NULL) {
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf("ra=%p sp=%p, ", ra, sp);
- method_print(m);
- printf(": extern stackframe parent");
- fflush(stdout);
- }
-#endif
+ tmpsfi->code = prevsfi->code;
+ tmpsfi->pv = prevsfi->pv;
+ tmpsfi->sp = prevsfi->sp;
+ tmpsfi->ra = prevsfi->ra;
+ tmpsfi->xpc = prevsfi->xpc;
-#if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-#endif
+ /* Set the previous stackframe info of the temporary one to
+ the next in the chain. */
- /* add the method to the stacktrace */
+ 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);
+ }
- stb = stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
+ return true;
+}
- /* get the current stack frame size */
- framesize = *((u4 *) (pv + FrameSize));
+/* stacktrace_create ***********************************************************
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf(", framesize=%d\n", framesize);
- fflush(stdout);
- }
-#endif
+ Generates a stacktrace from the thread passed into a
+ stacktracebuffer. The stacktracebuffer is allocated on the
+ dump memory.
+
+ NOTE: The first element in the stackframe chain must always be a
+ native stackframeinfo (e.g. VMThrowable.fillInStackTrace() is
+ a native function).
- /* Set stack pointer to stackframe of parent Java
- function of the current Java function. */
+ RETURN VALUE:
+ pointer to the stacktracebuffer, or
+ NULL if there is no stacktrace available for the
+ given thread.
-#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
- sp += framesize + SIZEOF_VOID_P;
-#elif defined(__SPARC_64__)
- sp = md_get_framepointer(sp);
-#else
- sp += framesize;
-#endif
+*******************************************************************************/
- /* get data segment and methodinfo pointer from
- parent method */
+stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi)
+{
+ stacktracebuffer *stb;
+ stackframeinfo_t tmpsfi;
+ bool skip_fillInStackTrace;
+ bool skip_init;
-#if defined(ENABLE_JIT)
- pv = md_codegen_get_pv_from_pc(ra);
-#endif
+ skip_fillInStackTrace = true;
+ skip_init = true;
- code = *((codeinfo **) (pv + CodeinfoPointer));
+ /* Create a stacktracebuffer in dump memory. */
- /* For asm_vm_call_method the codeinfo pointer is
- NULL. */
+ stb = DNEW(stacktracebuffer);
- m = (code == NULL) ? NULL : code->m;
+ stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
+ stb->used = 0;
-#if defined(ENABLE_INTRP)
- }
-#endif
- }
#if !defined(NDEBUG)
- else {
- if (opt_DebugStackTrace) {
- printf("ra=%p sp=%p, ", ra, sp);
- printf("asm_calljavafunction\n");
- fflush(stdout);
- }
- }
+ if (opt_DebugStackTrace) {
+ printf("\n\n---> stacktrace creation start (fillInStackTrace):\n");
+ fflush(stdout);
+ }
#endif
- }
-
- /* get previous stackframeinfo in the chain */
- sfi = sfi->prev;
+ /* Put the data from the stackframeinfo into a temporary one. */
- } else {
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf("ra=%p sp=%p, ", ra, sp);
- method_print(m);
- printf(": JIT");
- fflush(stdout);
- }
-#endif
+ /* XXX This is not correct, but a workaround for threads-dump for
+ now. */
+/* assert(sfi != NULL); */
+ if (sfi == NULL)
+ return NULL;
- /* JIT method found, add it to the stacktrace (we subtract
- 1 from the return address since it points the the
- instruction after call). */
+ tmpsfi.code = sfi->code;
+ tmpsfi.pv = sfi->pv;
+ tmpsfi.sp = sfi->sp;
+ tmpsfi.ra = sfi->ra;
+ tmpsfi.xpc = sfi->xpc;
- stb = stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
+ /* Initially set the previous stackframe info of the temporary one
+ to the next in the chain. */
- /* get the current stack frame size */
+ tmpsfi.prev = sfi->prev;
- framesize = *((u4 *) (pv + FrameSize));
+ /* Iterate till we're done. */
+ do {
#if !defined(NDEBUG)
- if (opt_DebugStackTrace) {
- printf(", framesize=%d\n", framesize);
- fflush(stdout);
- }
+ /* Print current method information. */
+
+ if (opt_DebugStackTrace) {
+ 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();
+ }
#endif
- /* get return address of current stack frame */
+ /* This logic is taken from
+ hotspot/src/share/vm/classfile/javaClasses.cpp
+ (java_lang_Throwable::fill_in_stack_trace). */
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
- else
-# endif
- ra = md_stacktrace_get_returnaddress(sp, framesize);
-#else
- ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
-#endif
+ if (skip_fillInStackTrace == true) {
+ /* Check "fillInStackTrace" only once, so we negate the
+ flag after the first time check. */
- /* get data segment and methodinfo pointer from parent method */
+#if defined(WITH_CLASSPATH_GNU)
+ /* For GNU Classpath we also need to skip
+ VMThrowable.fillInStackTrace(). */
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- pv = codegen_get_pv_from_pc(ra);
- else
-#endif
- {
-#if defined(ENABLE_JIT)
-# if defined(__SPARC_64__)
- sp = md_get_framepointer(sp);
- pv = md_get_pv_from_stackframe(sp);
-# else
- pv = md_codegen_get_pv_from_pc(ra);
-# endif
+ if ((tmpsfi.code->m->class == class_java_lang_VMThrowable) &&
+ (tmpsfi.code->m->name == utf_fillInStackTrace))
+ continue;
#endif
- }
- code = *((codeinfo **) (pv + CodeinfoPointer));
+ skip_fillInStackTrace = false;
- /* For asm_vm_call_method the codeinfo pointer is NULL. */
+ if (tmpsfi.code->m->name == utf_fillInStackTrace)
+ continue;
+ }
- m = (code == NULL) ? NULL : code->m;
+ /* 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. */
- /* walk the stack */
+ 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 defined(ENABLE_INTRP)
- if (opt_intrp)
- sp = *(u1 **) (sp - framesize);
- else
-#endif
- {
-#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
- sp += framesize + SIZEOF_VOID_P;
-#elif defined(__SPARC_64__)
- /* already has the new sp */
-#else
- sp += framesize;
-#endif
- }
+ skip_init = false;
+ }
}
- }
+
+ /* Add this method to the stacktrace. */
+
+ stb = stacktrace_method_add(stb, &tmpsfi);
+ } while (stacktrace_stack_walk(&tmpsfi) == true);
#if !defined(NDEBUG)
if (opt_DebugStackTrace) {
/* set up the 2-dimensional array */
- LLNI_objectarray_element_set(oa, 0, classes);
- LLNI_objectarray_element_set(oa, 1, methodnames);
+ array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
+ array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
/* iterate over all stacktrace entries */
if (string == NULL)
goto return_NULL;
- LLNI_objectarray_element_set(methodnames, i, string);
+ array_objectarray_element_set(methodnames, i, string);
}
/* return the 2-dimensional array */