* src/vm/jit/trace.c (trace_java_call_enter): Removed unused variable.
[cacao.git] / src / vm / jit / stacktrace.c
index beaae0c7716fec52f9a7d2ee8d01309758daa8d7..b8847deb3ad31d9638d5ffd242b252900d2a8437 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/stacktrace.c - machine independent stacktrace system
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Joseph Wenninger
-            Christian Thalinger
-            Edwin Steiner
-
-   $Id: stacktrace.c 6251 2006-12-27 23:15:56Z twisti $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include "mm/gc-common.h"
 #include "mm/memory.h"
-#include "native/native.h"
+
+#include "vm/jit/stacktrace.h"
 
 #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)
 #endif
 
 #include "toolbox/logging.h"
+
+#include "vm/array.h"
 #include "vm/builtin.h"
-#include "vm/class.h"
+#include "vm/cycles-stats.h"
 #include "vm/exceptions.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
+#include "vm/jit/linenumbertable.h"
 #include "vm/jit/methodheader.h"
-#include "vm/cycles-stats.h"
 
+#include "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
 
-/* global variables ***********************************************************/
 
+/* 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)
@@ -85,128 +85,27 @@ CYCLES_STATS_DECLARE(stacktrace_getCurrentClass ,40,5000)
 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
+       stackframeinfo_t **psfi;
+       codeinfo          *code;
+#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
+       bool               isleafmethod;
 #endif
-                       {
 #if defined(ENABLE_JIT)
-                               pv = md_codegen_get_pv_from_pc(ra);
+       s4                 framesize;
 #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_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;
-#if !defined(__I386__) && !defined(__X86_64__)
-       bool             isleafmethod;
-#endif
-#if defined(ENABLE_JIT)
-       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). */
@@ -219,20 +118,34 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 #endif
                        {
 #if defined(ENABLE_JIT)
+# if defined(__SPARC_64__)
+                               pv = md_get_pv_from_stackframe(sp);
+# else
                                pv = md_codegen_get_pv_from_pc(ra);
+# endif
 #endif
                        }
        }
 
+       /* 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__)
+# 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. */
 
                framesize = *((u4 *) (pv + FrameSize));
 
@@ -254,353 +167,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;
-
-       /* get current stackframe info pointer */
-
-       psfi = STACKFRAMEINFO;
-
-       /* restore the old pointer */
+       /* 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. */
 
-       *psfi = sfi->prev;
+       THREAD_NATIVEWORLD_ENTER;
 }
 
 
-/* stacktrace_inline_arithmeticexception ***************************************
+/* stacktrace_stackframeinfo_remove ********************************************
 
-   Creates an ArithemticException for inline stub.
+   Remove the given stackframeinfo from the chain in the current
+   thread.
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                u1 *ra, u1 *xpc)
+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 */
-
-       o = new_arithmeticexception();
-
-       /* remove stackframeinfo */
+       stackframeinfo_t **psfi;
 
-       stacktrace_remove_stackframeinfo(&sfi);
+       /* clear the native world flag for the current thread */
+       /* ATTENTION: Clear this flag _before_ removing the stackframe info */
 
-       return o;
-}
-
-
-/* stacktrace_inline_arrayindexoutofboundsexception ****************************
-
-   Creates an ArrayIndexOutOfBoundsException for inline stub.
-
-*******************************************************************************/
+       THREAD_NATIVEWORLD_EXIT;
 
-java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
-                                                                                                                                       u1 *sp,
-                                                                                                                                       u1 *ra,
-                                                                                                                                       u1 *xpc,
-                                                                                                                                       s4 index)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_arrayindexoutofboundsexception(index);
-
-       /* 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.
-
-*******************************************************************************/
-
-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 = 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 */
 
@@ -617,333 +290,331 @@ 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;
 
-       /* find the realization of the method the pc is in */
+       /* Get values from the stackframeinfo. */
 
-       code = *((codeinfo **) (pv + CodeinfoPointer));
+       code = sfi->code;
+       pv   = sfi->pv;
+       xpc  = sfi->xpc;
 
-       /* search the line number table */
+       m = code->m;
 
-       linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
+       /* Skip builtin methods. */
 
-       /* now add a new entry to the staktrace */
+       if (m->flags & ACC_METHOD_BUILTIN)
+               return stb;
 
-       stacktrace_add_entry(stb, m, linenumber);
+       /* Search the line number table. */
 
-       return true;
+       linenumber = linenumbertable_linenumber_for_pc(&m, code, xpc);
+
+       /* Add a new entry to the staktrace. */
+
+       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:
+       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(threadobject* thread)
+static inline bool stacktrace_stack_walk(stackframeinfo_t *tmpsfi)
 {
-       stacktracebuffer *stb;
-       stackframeinfo   *sfi;
-       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);
-
-       stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
-       stb->used     = 0;
-       stb->entries  = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
-
-       /* 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;
+       ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
 #endif
 
-#define PRINTMETHODS 0
+       /* Get the PV for the parent Java method. */
 
-#if PRINTMETHODS
-       printf("\n\nfillInStackTrace start:\n");
-       fflush(stdout);
+#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
+               }
 
-       /* 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;
+       /* Get the codeinfo pointer for the parent Java method. */
 
-                               if (m)
-                                       stacktrace_add_entry(stb, m, 0);
+       code = code_get_codeinfo_for_pv(pv);
 
-#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*). */
+       /* Calculate the SP for the parent Java method. */
 
 #if defined(ENABLE_INTRP)
-                               if (opt_intrp)
-                                       pv = codegen_get_pv_from_pc(ra);
-                               else
+       if (opt_intrp)
+               sp = *(u1 **) (sp - framesize);
+       else
 #endif
-                                       {
-#if defined(ENABLE_JIT)
-                                               pv = md_codegen_get_pv_from_pc(ra);
+               {
+#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 pointer from parent data segment */
-
-                               code = *((codeinfo **) (pv + CodeinfoPointer));
+               }
 
-                               /* For asm_vm_call_method the codeinfo pointer is
-                                  NULL. */
+       /* 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. */
 
-                               m = (code == NULL) ? NULL : code->m;
+       if (code == NULL) {
+               prevsfi = tmpsfi->prev;
 
-                       } 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!!! */
+               /* If the previous stackframeinfo in the chain is NULL we
+                  reached the top of the stacktrace and return false. */
 
-                               /* get methodinfo, sp and ra from the current stackframe info */
+               if (prevsfi == NULL)
+                       return false;
 
-                               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          */
+               /* Fill the temporary stackframeinfo with the new values. */
 
-#if PRINTMETHODS
-                               printf("ra=%p sp=%p, ", ra, sp);
-                               printf("NULL: inline stub\n");
-                               fflush(stdout);
-#endif
+               tmpsfi->code = prevsfi->code;
+               tmpsfi->pv   = prevsfi->pv;
+               tmpsfi->sp   = prevsfi->sp;
+               tmpsfi->ra   = prevsfi->ra;
+               tmpsfi->xpc  = prevsfi->xpc;
 
-                               /* get methodinfo from current Java method */
+               /* Set the previous stackframe info of the temporary one to
+                  the next in the chain. */
 
-                               code = *((codeinfo **) (pv + CodeinfoPointer));
+               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);
+       }
 
-                               /* For asm_vm_call_method the codeinfo pointer is
-                                  NULL. */
+       return true;
+}
 
-                               m = (code == NULL) ? NULL : code->m;
 
-                               /* if m == NULL, this is a asm_calljavafunction call */
+/* stacktrace_create ***********************************************************
 
-                               if (m != NULL) {
-#if PRINTMETHODS
-                                       printf("ra=%p sp=%p, ", ra, sp);
-                                       method_print(m);
-                                       printf(": inline stub parent");
-                                       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).
 
-#if defined(ENABLE_INTRP)
-                                       if (!opt_intrp) {
-#endif
+   RETURN VALUE:
+      pointer to the stacktracebuffer, or
+      NULL if there is no stacktrace available for the
+      given thread.
 
-                                       /* add the method to the stacktrace */
+*******************************************************************************/
 
-                                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
+stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi)
+{
+       stacktracebuffer *stb;
+       stackframeinfo_t  tmpsfi;
+       bool              skip_fillInStackTrace;
+       bool              skip_init;
 
-                                       /* get the current stack frame size */
+       skip_fillInStackTrace = true;
+       skip_init             = true;
 
-                                       framesize = *((u4 *) (pv + FrameSize));
+       /* Create a stacktracebuffer in dump memory. */
 
-#if PRINTMETHODS
-                                       printf(", framesize=%d\n", framesize);
-                                       fflush(stdout);
-#endif
+       stb = DNEW(stacktracebuffer);
 
-                                       /* Set stack pointer to stackframe of parent Java
-                                          function of the current Java function. */
+       stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
+       stb->used     = 0;
 
-#if defined(__I386__) || defined (__X86_64__)
-                                       sp += framesize + SIZEOF_VOID_P;
-#else
-                                       sp += framesize;
+#if !defined(NDEBUG)
+       if (opt_DebugStackTrace) {
+               printf("\n\n---> stacktrace creation start (fillInStackTrace):\n");
+               fflush(stdout);
+       }
 #endif
 
-                                       /* get data segment and methodinfo pointer from
-                                          parent method */
-
-#if defined(ENABLE_JIT)
-                                       pv = md_codegen_get_pv_from_pc(ra);
-#endif
+       /* Put the data from the stackframeinfo into a temporary one. */
 
-                                       code = *((codeinfo **) (pv + CodeinfoPointer));
+       /* XXX This is not correct, but a workaround for threads-dump for
+          now. */
+/*     assert(sfi != NULL); */
+       if (sfi == NULL)
+               return NULL;
 
-                                       /* For asm_vm_call_method the codeinfo pointer is
-                                          NULL. */
+       tmpsfi.code = sfi->code;
+       tmpsfi.pv   = sfi->pv;
+       tmpsfi.sp   = sfi->sp;
+       tmpsfi.ra   = sfi->ra;
+       tmpsfi.xpc  = sfi->xpc;
 
-                                       m = (code == NULL) ? NULL : code->m;
+       /* Initially set the previous stackframe info of the temporary one
+          to the next in the chain. */
 
-#if defined(ENABLE_INTRP)
-                                       }
-#endif
-                               }
-#if PRINTMETHODS
-                               else {
-                                       printf("ra=%p sp=%p, ", ra, sp);
-                                       printf("asm_calljavafunction\n");
-                                       fflush(stdout);
-                               }
-#endif
-                       }
+       tmpsfi.prev = sfi->prev;
 
-                       /* get previous stackframeinfo in the chain */
+       /* Iterate till we're done. */
 
-                       sfi = sfi->prev;
+       do {
+#if !defined(NDEBUG)
+               /* Print current method information. */
 
-               } else {
-#if PRINTMETHODS
-                       printf("ra=%p sp=%p, ", ra, sp);
-                       method_print(m);
-                       printf(": JIT");
-                       fflush(stdout);
+               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
 
-                       /* JIT method found, add it to the stacktrace (we subtract
-                          1 from the return address since it points the the
-                          instruction after call). */
-
-                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
+               /* This logic is taken from
+                  hotspot/src/share/vm/classfile/javaClasses.cpp
+                  (java_lang_Throwable::fill_in_stack_trace). */
 
-                       /* get the current stack frame size */
+               if (skip_fillInStackTrace == true) {
+                       /* Check "fillInStackTrace" only once, so we negate the
+                          flag after the first time check. */
 
-                       framesize = *((u4 *) (pv + FrameSize));
+#if defined(WITH_CLASSPATH_GNU)
+                       /* For GNU Classpath we also need to skip
+                          VMThrowable.fillInStackTrace(). */
 
-#if PRINTMETHODS
-                       printf(", framesize=%d\n", framesize);
-                       fflush(stdout);
+                       if ((tmpsfi.code->m->class == class_java_lang_VMThrowable) &&
+                               (tmpsfi.code->m->name  == utf_fillInStackTrace))
+                               continue;
 #endif
 
-                       /* get return address of current stack frame */
-
-#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
+                       skip_fillInStackTrace = false;
 
-                       /* get data segment and methodinfo pointer from parent method */
+                       if (tmpsfi.code->m->name == utf_fillInStackTrace)
+                               continue;
+               }
 
-#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
-                               }
+               /* 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. */
 
-                       code = *((codeinfo **) (pv + CodeinfoPointer));
+               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. */
 
-                       /* For asm_vm_call_method the codeinfo pointer is NULL. */
+                               skip_init = false;
+                       }
+               }
 
-                       m = (code == NULL) ? NULL : code->m;
+               /* Add this method to the stacktrace. */
 
-                       /* walk the stack */
+               stb = stacktrace_method_add(stb, &tmpsfi);
+       } while (stacktrace_stack_walk(&tmpsfi) == true);
 
-#if defined(ENABLE_INTRP)
-                       if (opt_intrp)
-                               sp = *(u1 **) (sp - framesize);
-                       else
-#endif
-                               {
-#if defined(__I386__) || defined (__X86_64__)
-                                       sp += framesize + SIZEOF_VOID_P;
-#else
-                                       sp += framesize;
-#endif
-                               }
-               }
+#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;
 }
 
 
@@ -954,12 +625,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 */
@@ -968,26 +639,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 */
 
@@ -995,7 +663,7 @@ stacktracecontainer *stacktrace_fillInStackTrace(void)
 
        CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
                                                                   stacktrace_overhead)
-       return gcstc;
+       return ba;
 
 return_NULL:
        dump_release(dumpsize);
@@ -1017,14 +685,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 */
@@ -1033,8 +701,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 */
@@ -1064,7 +733,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 */
@@ -1117,8 +786,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
@@ -1165,17 +835,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_lang_String *str;
-       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 */
@@ -1184,7 +854,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;
@@ -1212,21 +882,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;
-               str = javastring_new(ste->method->name);
+               LLNI_array_direct(classes, i) = (java_object_t *) c;
+
+               string = javastring_new(ste->method->name);
 
-               if (str == NULL)
+               if (string == NULL)
                        goto return_NULL;
 
-               methodnames->data[i] = (java_objectheader *) str;
+               array_objectarray_element_set(methodnames, i, string);
        }
 
        /* return the 2-dimensional array */
@@ -1288,61 +959,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;
-
-#if 0
-       /* get methodinfo pointer from data segment */
-
-       m = *((methodinfo **) (pv + MethodPointer));
-
-       /* get current stackframe info pointer */
-
-       psfi = STACKFRAMEINFO;
-
-       /* fill new stackframe info structure */
-
-       sfi->prev   = *psfi;
-       sfi->method = NULL;
-       sfi->pv     = NULL;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-
-       /* store new stackframe info pointer */
-
-       *psfi = sfi;
-#endif
-
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       /* create a stacktrace for the current thread */
-
-       stb = stacktrace_create(thread);
-
-       /* print stacktrace */
-
-       if (stb)
-               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
@@ -1350,14 +966,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;
 
@@ -1367,14 +983,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);
 }