* src/vm/exceptions.c (exceptions_handle_exception): Use
[cacao.git] / src / vm / jit / stacktrace.c
index 883cee7ead3b19d7d15f12bf10d578d980dbfb0e..02ed7f89e21e86ef4224deb12cbb86e365dd4ca2 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: stacktrace.c 7356 2007-02-14 11:00:28Z twisti $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -42,6 +41,7 @@
 
 #include "vm/global.h"                   /* required here for native includes */
 #include "native/jni.h"
+#include "native/llni.h"
 #include "native/include/java_lang_Throwable.h"
 
 #if defined(WITH_CLASSPATH_GNU)
@@ -56,6 +56,7 @@
 
 #include "toolbox/logging.h"
 
+#include "vm/array.h"
 #include "vm/builtin.h"
 #include "vm/cycles-stats.h"
 #include "vm/exceptions.h"
@@ -73,7 +74,7 @@
 
 /* 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)
@@ -83,128 +84,27 @@ CYCLES_STATS_DECLARE(stacktrace_getCurrentClass ,40,5000)
 CYCLES_STATS_DECLARE(stacktrace_getStack        ,40,10000)
 
 
-/* stacktrace_create_stackframeinfo ********************************************
-
-   Creates an stackframe info structure for inline code in the
-   interpreter.
-
-*******************************************************************************/
-
-#if defined(ENABLE_INTRP)
-void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
-                                                                         u1 *ra)
-{
-       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_inline_stackframeinfo *************************************
-
-   Creates an stackframe info structure for an inline exception stub.
-
-*******************************************************************************/
-
-void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
-                                                                                        u1 *sp, u1 *ra, u1 *xpc)
-{
-       stackframeinfo **psfi;
-
-       /* get current stackframe info pointer */
-
-       psfi = STACKFRAMEINFO;
-
-#if defined(ENABLE_INTRP)
-       if (opt_intrp) {
-               /* if we don't have pv handy */
-
-               if (pv == NULL)
-                       pv = codegen_get_pv_from_pc(ra);
-
-       }
-#endif
-
-       /* 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;
-}
+/* stacktrace_stackframeinfo_add ***********************************************
 
-
-/* stacktrace_create_extern_stackframeinfo *************************************
-
-   Creates an stackframe info structure for an extern exception
-   (hardware or assembler).
+   Fills a stackframe info structure with the given or calculated
+   values and adds it to the chain.
 
 *******************************************************************************/
 
-void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
-                                                                                        u1 *sp, u1 *ra, u1 *xpc)
+void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
 {
-       stackframeinfo **psfi;
-#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__)
-       bool             isleafmethod;
+       stackframeinfo_t **psfi;
+       codeinfo          *code;
+#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
+       bool               isleafmethod;
 #endif
 #if defined(ENABLE_JIT)
-       s4               framesize;
+       s4                 framesize;
 #endif
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        /* sometimes we don't have pv handy (e.g. in asmpart.S:
        L_asm_call_jit_compiler_exception or in the interpreter). */
@@ -226,15 +126,23 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
                        }
        }
 
+       /* 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 (!opt_intrp) {
 # endif
-# if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
+# if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
                /* On i386 and x86_64 we always have to get the return address
                   from the stack. */
+               /* m68k has return address on stack always */
                /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
                   the RA from stack. */
 
@@ -258,353 +166,113 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 # 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;
-}
-
-
-/* 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. */
-
-       m = (code == NULL) ? NULL : code->m;
-
-       /* get current stackframe info pointer */
+#endif
 
-       psfi = STACKFRAMEINFO;
+       /* 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. */
 
-       /* fill new stackframe info structure */
+       if (xpc == NULL) {
+               xpc = (void *) (((intptr_t) ra) - 1);
+       }
 
-       sfi->prev   = *psfi;
-       sfi->method = m;
-       sfi->pv     = NULL;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-       sfi->xpc    = NULL;
+       /* Fill new stackframeinfo structure. */
+
+       sfi->prev = *psfi;
+       sfi->code = code;
+       sfi->pv   = pv;
+       sfi->sp   = sp;
+       sfi->ra   = ra;
+       sfi->xpc  = xpc;
+
+#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 ********************************************
-
-   Remove the topmost stackframeinfo in the current thread.
-
-*******************************************************************************/
-
-void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
-{
-       stackframeinfo **psfi;
+       /* 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. */
 
-       /* get current stackframe info pointer */
-
-       psfi = STACKFRAMEINFO;
-
-       /* restore the old pointer */
-
-       *psfi = sfi->prev;
-}
-
-
-/* stacktrace_inline_arithmeticexception ***************************************
-
-   Creates an ArithemticException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = exceptions_new_arithmeticexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
+       THREAD_NATIVEWORLD_ENTER;
 }
 
 
-/* stacktrace_inline_arrayindexoutofboundsexception ****************************
+/* stacktrace_stackframeinfo_remove ********************************************
 
-   Creates an ArrayIndexOutOfBoundsException for inline stub.
+   Remove the given stackframeinfo from the chain in the current
+   thread.
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
-                                                                                                                                       u1 *sp,
-                                                                                                                                       u1 *ra,
-                                                                                                                                       u1 *xpc,
-                                                                                                                                       s4 index)
+void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
 {
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
+       stackframeinfo_t **psfi;
 
-       o = exceptions_new_arrayindexoutofboundsexception(index);
+       /* clear the native world flag for the current thread */
+       /* ATTENTION: Clear this flag _before_ removing the stackframe info */
 
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_arraystoreexception ***************************************
-
-   Creates an ArrayStoreException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                                u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = exceptions_new_arraystoreexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_classcastexception ****************************************
-
-   Creates an ClassCastException for inline stub.
-
-*******************************************************************************/
+       THREAD_NATIVEWORLD_EXIT;
 
-java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                               u1 *xpc,
-                                                                                                               java_objectheader *o)
-{
-       stackframeinfo     sfi;
-       java_objectheader *e;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       e = exceptions_new_classcastexception(o);
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return e;
-}
-
-
-/* stacktrace_inline_nullpointerexception **************************************
-
-   Creates an NullPointerException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                 u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = exceptions_new_nullpointerexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_fillInStackTrace ******************************************
-
-   Fills in the correct stacktrace into an existing exception object
-   (this one is for inline exception stubs).
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                         u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-       methodinfo        *m;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* get exception */
-
-       o = *exceptionptr;
-       assert(o);
-
-       /* clear exception */
-
-       *exceptionptr = NULL;
+       /* get current stackframe info pointer */
 
-       /* resolve methodinfo pointer from exception object */
+       psfi = &STACKFRAMEINFO;
 
-#if defined(ENABLE_JAVASE)
-       m = class_resolvemethod(o->vftbl->class,
-                                                       utf_fillInStackTrace,
-                                                       utf_void__java_lang_Throwable);
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-       m = class_resolvemethod(o->vftbl->class,
-                                                       utf_fillInStackTrace,
-                                                       utf_void__void);
-#else
-#error IMPLEMENT ME!
+#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
 
-       /* call function */
-
-       (void) vm_call_method(m, o);
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_hardware_arithmeticexception *************************************
-
-   Creates an ArithemticException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                  u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = exceptions_new_arithmeticexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_hardware_nullpointerexception ************************************
-
-   Creates an NullPointerException for the SIGSEGV signal handler.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                       u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = exceptions_new_nullpointerexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
+       /* restore the old pointer */
 
-       return o;
+       *psfi = sfi->prev;
 }
 
 
-/* stacktrace_add_entry ********************************************************
+/* stacktrace_entry_add ********************************************************
 
    Adds a new entry to the stacktrace buffer.
 
 *******************************************************************************/
 
-static void 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;
+       u4                stb_size_new;
 
        /* check if we already reached the buffer capacity */
 
        if (stb->used >= stb->capacity) {
+               /* calculate size of stacktracebuffer */
+
+               stb_size_old = sizeof(stacktracebuffer) +
+                                          sizeof(stacktrace_entry) * stb->capacity -
+                                          sizeof(stacktrace_entry) * STACKTRACE_CAPACITY_DEFAULT;
+
+               stb_size_new = stb_size_old +
+                                          sizeof(stacktrace_entry) * STACKTRACE_CAPACITY_INCREMENT;
+
                /* reallocate new memory */
 
-               stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
-                                                                stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
+               stb = DMREALLOC(stb, u1, stb_size_old, stb_size_new);
 
                /* set new buffer capacity */
 
@@ -621,342 +289,280 @@ static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
        /* increase entries used count */
 
        stb->used += 1;
+
+       return stb;
 }
 
 
-/* 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:
-       true, if stacktrace entries were successfully created, false otherwise.
+       stacktracebuffer after possible reallocation.
 
    [1] In case of inlined methods there may be more than one stacktrace
        entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
 
 *******************************************************************************/
 
-static bool 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. */
+
+       code = sfi->code;
+       pv   = sfi->pv;
+       xpc  = sfi->xpc;
 
-       /* find the realization of the method the pc is in */
+       m = code->m;
 
-       code = *((codeinfo **) (pv + CodeinfoPointer));
+       /* Skip builtin methods. */
 
-       /* search the line number table */
+       if (m->flags & ACC_METHOD_BUILTIN)
+               return stb;
 
-       linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
+       /* Search the line number table. */
 
-       /* now add a new entry to the staktrace */
+       linenumber = dseg_get_linenumber_from_pc(&m, pv, xpc);
 
-       stacktrace_add_entry(stb, m, linenumber);
+       /* Add a new entry to the staktrace. */
 
-       return true;
+       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 GC
-   heap.
+   Walk the stack (or the stackframeinfo-chain) to the next method.
 
-   RETURN VALUE:
-      pointer to the stacktracebuffer, or
-         NULL if an exception has been thrown
+   IN:
+       sfi....stackframeinfo of current method
 
 *******************************************************************************/
 
-stacktracebuffer *stacktrace_create(threadobject* thread)
+static inline void stacktrace_stack_walk(stackframeinfo_t *sfi)
 {
-       stacktracebuffer *stb;
-       stackframeinfo   *sfi;
-       methodinfo       *m;
-       codeinfo         *code;
-       u1               *pv;
-       u1               *sp;
-       u4                framesize;
-       u1               *ra;
-       u1               *xpc;
-
-       /* prevent compiler warnings */
+       codeinfo *code;
+       void     *pv;
+       void     *sp;
+       void     *ra;
+       void     *xpc;
+       uint32_t  framesize;
 
-       pv = NULL;
-       sp = NULL;
-       ra = NULL;
+       /* Get values from the stackframeinfo. */
 
-       /* create a stacktracebuffer in dump memory */
+       code = sfi->code;
+       pv   = sfi->pv;
+       sp   = sfi->sp;
+       ra   = sfi->ra;
+       xpc  = sfi->xpc;
 
-       stb = DNEW(stacktracebuffer);
-
-       stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
-       stb->used     = 0;
-       stb->entries  = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
+       /* Get the current stack frame size. */
 
-       /* The first element in the stackframe chain must always be a
-          native stackframeinfo (VMThrowable.fillInStackTrace is a native
-          function). */
+       framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
 
-       /* We don't use the STACKFRAMEINFO macro here, as we have to use
-          the passed thread. */
+       /* 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(ENABLE_THREADS)
-       sfi = thread->_stackframeinfo;
+#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
-       sfi = _no_threads_stackframeinfo;
-#endif
-
-#define PRINTMETHODS 0
-
-#if PRINTMETHODS
-       printf("\n\nfillInStackTrace start:\n");
-       fflush(stdout);
+       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)
-                                       stacktrace_add_entry(stb, m, 0);
-
-#if PRINTMETHODS
-                               printf("ra=%p sp=%p, ", ra, sp);
-                               method_print(m);
-                               printf(": native 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);
-#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 methodinfo, sp and ra from the current stackframe info */
-
-                               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          */
-
-#if PRINTMETHODS
-                               printf("ra=%p sp=%p, ", ra, sp);
-                               printf("NULL: inline stub\n");
-                               fflush(stdout);
+# 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 from current Java method */
-
-                               code = *((codeinfo **) (pv + CodeinfoPointer));
-
-                               /* For asm_vm_call_method the codeinfo pointer is
-                                  NULL. */
+       /* Get the codeinfo pointer for the parent Java method. */
 
-                               m = (code == NULL) ? NULL : code->m;
+       code = code_get_codeinfo_for_pv(pv);
 
-                               /* if m == NULL, this is a asm_calljavafunction call */
-
-                               if (m != NULL) {
-#if PRINTMETHODS
-                                       printf("ra=%p sp=%p, ", ra, sp);
-                                       method_print(m);
-                                       printf(": inline stub parent");
-                                       fflush(stdout);
-#endif
+       /* Calculate the SP for the parent Java method. */
 
 #if defined(ENABLE_INTRP)
-                                       if (!opt_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
+               }
 
-                                       /* add the method to the stacktrace */
-
-                                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
+       /* 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. */
 
-                                       /* get the current stack frame size */
+       sfi->code = code;
+       sfi->pv   = pv;
+       sfi->sp   = sp;
+       sfi->ra   = ra;
+       sfi->xpc  = (void *) (((intptr_t) ra) - 1);
+}
 
-                                       framesize = *((u4 *) (pv + FrameSize));
 
-#if PRINTMETHODS
-                                       printf(", framesize=%d\n", framesize);
-                                       fflush(stdout);
-#endif
+/* stacktrace_create ***********************************************************
 
-                                       /* Set stack pointer to stackframe of parent Java
-                                          function of the current Java function. */
+   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).
 
-#if defined(__I386__) || defined (__X86_64__)
-                                       sp += framesize + SIZEOF_VOID_P;
-#elif defined(__SPARC_64__)
-                                       sp = md_get_framepointer(sp);
-#else
-                                       sp += framesize;
-#endif
+   RETURN VALUE:
+      pointer to the stacktracebuffer, or
+      NULL if there is no stacktrace available for the
+      given thread.
 
-                                       /* get data segment and methodinfo pointer from
-                                          parent method */
+*******************************************************************************/
 
-#if defined(ENABLE_JIT)
-                                       pv = md_codegen_get_pv_from_pc(ra);
-#endif
+stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi)
+{
+       stacktracebuffer *stb;
+       stackframeinfo_t  tmpsfi;
 
-                                       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 PRINTMETHODS
-                               else {
-                                       printf("ra=%p sp=%p, ", ra, sp);
-                                       printf("asm_calljavafunction\n");
-                                       fflush(stdout);
-                               }
+#if !defined(NDEBUG)
+       if (opt_DebugStackTrace) {
+               printf("\n\n---> stacktrace creation start (fillInStackTrace):\n");
+               fflush(stdout);
+       }
 #endif
-                       }
 
-                       /* get previous stackframeinfo in the chain */
+       /* Put the data from the stackframeinfo into a temporary one. */
 
-                       sfi = sfi->prev;
+       /* XXX This is not correct, but a workaround for threads-dump for
+          now. */
+/*     assert(sfi != NULL); */
+       if (sfi == NULL)
+               return NULL;
 
-               } else {
-#if PRINTMETHODS
-                       printf("ra=%p sp=%p, ", ra, sp);
-                       method_print(m);
-                       printf(": JIT");
-                       fflush(stdout);
-#endif
+       tmpsfi.code = sfi->code;
+       tmpsfi.pv   = sfi->pv;
+       tmpsfi.sp   = sfi->sp;
+       tmpsfi.ra   = sfi->ra;
+       tmpsfi.xpc  = sfi->xpc;
 
-                       /* JIT method found, add it to the stacktrace (we subtract
-                          1 from the return address since it points the the
-                          instruction after call). */
+       /* Iterate till we're done. */
 
-                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
+       for (;;) {
+#if !defined(NDEBUG)
+               /* Print current method information. */
 
-                       /* get the current stack frame size */
+               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
 
-                       framesize = *((u4 *) (pv + FrameSize));
+               /* Check for Throwable.fillInStackTrace(). */
 
-#if PRINTMETHODS
-                       printf(", framesize=%d\n", framesize);
-                       fflush(stdout);
-#endif
+/*             if (tmpsfi.method->name != utf_fillInStackTrace) { */
+                       
+                       /* Add this method to the stacktrace. */
 
-                       /* get return address of current stack frame */
+                       stb = stacktrace_method_add(stb, &tmpsfi);
+/*             } */
 
-#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
+               /* Walk the stack (or the stackframeinfo chain) and get the
+                  next method. */
 
-                       /* get data segment and methodinfo pointer from parent method */
+               stacktrace_stack_walk(&tmpsfi);
 
-#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
-#endif
-                               }
+               /* 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 (tmpsfi.code == NULL) {
+                       sfi = sfi->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 leave the
+                          loop. */
 
-                       m = (code == NULL) ? NULL : code->m;
+                       if (sfi == NULL)
+                               break;
 
-                       /* walk the stack */
+                       /* Fill the temporary stackframeinfo with the new
+                          values. */
 
-#if defined(ENABLE_INTRP)
-                       if (opt_intrp)
-                               sp = *(u1 **) (sp - framesize);
-                       else
-#endif
-                               {
-#if defined(__I386__) || defined (__X86_64__)
-                                       sp += framesize + SIZEOF_VOID_P;
-#elif defined(__SPARC_64__)
-                                       /* already has the new sp */
-#else
-                                       sp += framesize;
-#endif
-                               }
+                       tmpsfi.code = sfi->code;
+                       tmpsfi.pv   = sfi->pv;
+                       tmpsfi.sp   = sfi->sp;
+                       tmpsfi.ra   = sfi->ra;
+                       tmpsfi.xpc  = sfi->xpc;
                }
        }
 
+#if !defined(NDEBUG)
+       if (opt_DebugStackTrace) {
+               printf("---> stacktrace creation finished.\n\n");
+               fflush(stdout);
+       }
+#endif
+
        /* return the stacktracebuffer */
 
-       return stb;
+       if (stb->used == 0)
+               return NULL;
+       else
+               return stb;
 }
 
 
@@ -967,12 +573,12 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
 
 *******************************************************************************/
 
-stacktracecontainer *stacktrace_fillInStackTrace(void)
+java_handle_bytearray_t *stacktrace_fillInStackTrace(void)
 {
-       stacktracebuffer    *stb;
-       stacktracecontainer *gcstc;
-       s4                   gcstc_size;
-       s4                   dumpsize;
+       stacktracebuffer        *stb;
+       java_handle_bytearray_t *ba;
+       s4                       ba_size;
+       s4                       dumpsize;
        CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
 
        /* mark start of dump memory area */
@@ -981,26 +587,23 @@ stacktracecontainer *stacktrace_fillInStackTrace(void)
 
        /* create a stacktrace from the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
-       if (!stb)
+       stb = stacktrace_create(STACKFRAMEINFO);
+
+       if (stb == NULL)
                goto return_NULL;
 
        /* allocate memory from the GC heap and copy the stacktrace buffer */
-       /* ATTENTION: use stacktracecontainer for this and make it look like
-       an array */
+       /* ATTENTION: use a bytearray for this to not confuse the GC */
 
-       gcstc_size = sizeof(stacktracebuffer) +
-                    sizeof(stacktrace_entry) * stb->used;
-       gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
+       ba_size = sizeof(stacktracebuffer) +
+                 sizeof(stacktrace_entry) * stb->used -
+                 sizeof(stacktrace_entry) * STACKTRACE_CAPACITY_DEFAULT;
+       ba = builtin_newarray_byte(ba_size);
 
-       if (gcstc == NULL)
+       if (ba == NULL)
                goto return_NULL;
 
-       gcstc->stb.capacity = stb->capacity;
-       gcstc->stb.used     = stb->used;
-       gcstc->stb.entries  = gcstc->data;
-
-       MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
+       MCOPY(LLNI_array_data(ba), stb, u1, ba_size);
 
        /* release dump memory */
 
@@ -1008,7 +611,7 @@ stacktracecontainer *stacktrace_fillInStackTrace(void)
 
        CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
                                                                   stacktrace_overhead)
-       return gcstc;
+       return ba;
 
 return_NULL:
        dump_release(dumpsize);
@@ -1030,14 +633,14 @@ return_NULL:
 
 *******************************************************************************/
 
-java_objectarray *stacktrace_getClassContext(void)
+java_handle_objectarray_t *stacktrace_getClassContext(void)
 {
-       stacktracebuffer  *stb;
-       stacktrace_entry  *ste;
-       java_objectarray  *oa;
-       s4                 oalength;
-       s4                 i;
-       s4                 dumpsize;
+       stacktracebuffer          *stb;
+       stacktrace_entry          *ste;
+       java_handle_objectarray_t *oa;
+       s4                         oalength;
+       s4                         i;
+       s4                         dumpsize;
        CYCLES_STATS_DECLARE_AND_START
 
        /* mark start of dump memory area */
@@ -1046,8 +649,9 @@ java_objectarray *stacktrace_getClassContext(void)
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
-       if (!stb)
+       stb = stacktrace_create(STACKFRAMEINFO);
+
+       if (stb == NULL)
                goto return_NULL;
 
        /* calculate the size of the Class array */
@@ -1077,7 +681,7 @@ java_objectarray *stacktrace_getClassContext(void)
                        continue;
                }
 
-               oa->data[i] = (java_objectheader *) ste->method->class;
+               LLNI_array_direct(oa, i) = (java_object_t *) ste->method->class;
        }
 
        /* release dump memory */
@@ -1130,8 +734,9 @@ classinfo *stacktrace_getCurrentClass(void)
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
-       if (!stb)
+       stb = stacktrace_create(STACKFRAMEINFO);
+
+       if (stb == NULL)
                goto return_NULL; /* XXX exception: how to distinguish from normal NULL return? */
 
        /* iterate over all stacktrace entries and find the first suitable
@@ -1178,17 +783,17 @@ return_NULL:
 *******************************************************************************/
 
 #if defined(ENABLE_JAVASE)
-java_objectarray *stacktrace_getStack(void)
+java_handle_objectarray_t *stacktrace_getStack(void)
 {
-       stacktracebuffer  *stb;
-       stacktrace_entry  *ste;
-       java_objectarray  *oa;
-       java_objectarray  *classes;
-       java_objectarray  *methodnames;
-       classinfo         *c;
-       java_objectheader *string;
-       s4                 i;
-       s4                 dumpsize;
+       stacktracebuffer          *stb;
+       stacktrace_entry          *ste;
+       java_handle_objectarray_t *oa;
+       java_handle_objectarray_t *classes;
+       java_handle_objectarray_t *methodnames;
+       classinfo                 *c;
+       java_handle_t             *string;
+       s4                         i;
+       s4                         dumpsize;
        CYCLES_STATS_DECLARE_AND_START
 
        /* mark start of dump memory area */
@@ -1197,7 +802,7 @@ java_objectarray *stacktrace_getStack(void)
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
+       stb = stacktrace_create(STACKFRAMEINFO);
 
        if (stb == NULL)
                goto return_NULL;
@@ -1225,22 +830,22 @@ java_objectarray *stacktrace_getStack(void)
 
        /* set up the 2-dimensional array */
 
-       oa->data[0] = (java_objectheader *) classes;
-       oa->data[1] = (java_objectheader *) 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 */
 
        for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
                c = ste->method->class;
 
-               classes->data[i] = (java_objectheader *) c;
+               LLNI_array_direct(classes, i) = (java_object_t *) c;
 
                string = javastring_new(ste->method->name);
 
                if (string == NULL)
                        goto return_NULL;
 
-               methodnames->data[i] = string;
+               array_objectarray_element_set(methodnames, i, string);
        }
 
        /* return the 2-dimensional array */
@@ -1302,39 +907,6 @@ void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
 }
 
 
-/* stacktrace_dump_trace *******************************************************
-
-   This method is call from signal_handler_sigusr1 to dump the
-   stacktrace of the current thread to stdout.
-
-*******************************************************************************/
-
-void stacktrace_dump_trace(threadobject *thread)
-{
-       stacktracebuffer *stb;
-       s4                dumpsize;
-
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       /* create a stacktrace for the current thread */
-
-       stb = stacktrace_create(thread);
-
-       /* print stacktrace */
-
-       if (stb != NULL)
-               stacktrace_print_trace_from_buffer(stb);
-       else {
-               puts("\t<<No stacktrace available>>");
-               fflush(stdout);
-       }
-
-       dump_release(dumpsize);
-}
-
-
 /* stacktrace_print_trace ******************************************************
 
    Print the stacktrace of a given exception. More or less a wrapper
@@ -1342,14 +914,14 @@ void stacktrace_dump_trace(threadobject *thread)
 
 *******************************************************************************/
 
-void stacktrace_print_trace(java_objectheader *xptr)
+void stacktrace_print_trace(java_handle_t *xptr)
 {
-       java_lang_Throwable   *t;
+       java_lang_Throwable     *t;
 #if defined(WITH_CLASSPATH_GNU)
-       java_lang_VMThrowable *vmt;
+       java_lang_VMThrowable   *vmt;
 #endif
-       stacktracecontainer   *stc;
-       stacktracebuffer      *stb;
+       java_handle_bytearray_t *ba;
+       stacktracebuffer        *stb;
 
        t = (java_lang_Throwable *) xptr;
 
@@ -1359,14 +931,17 @@ void stacktrace_print_trace(java_objectheader *xptr)
        /* now print the stacktrace */
 
 #if defined(WITH_CLASSPATH_GNU)
-       vmt = t->vmState;
-       stc = (stacktracecontainer *) vmt->vmData;
-       stb = &(stc->stb);
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-       stc = (stacktracecontainer *) t->backtrace;
-       stb = &(stc->stb);
+       LLNI_field_get_ref(t, vmState, vmt);
+       LLNI_field_get_ref(vmt, vmData, ba);
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+       LLNI_field_get_ref(t, backtrace, ba);
+#else
+# error unknown classpath configuration
 #endif
 
+       assert(ba);
+       stb = (stacktracebuffer *) LLNI_array_data(ba);
+
        stacktrace_print_trace_from_buffer(stb);
 }