* src/vm/jit/alpha/md.c (md_init): Smaller changes.
[cacao.git] / src / vm / jit / stacktrace.c
index 5964884e86255ba0fa927f529ce49a3f1da50938..a6854317917c7822a369e1552b2637c03827b19c 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/stacktrace.c - machine independet stacktrace system
+/* 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
-
-   Changes: Christian Thalinger
-            Edwin Steiner
-
-   $Id: stacktrace.c 4807 2006-04-21 13:08:00Z edwin $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "vm/types.h"
 
-#include "mm/boehm.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/include/java_lang_ClassLoader.h"
+#include "native/jni.h"
+#include "native/llni.h"
 #include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_VMThrowable.h"
 
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-#  include "threads/native/threads.h"
-# else
-#  include "threads/green/threads.h"
-# endif
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_VMThrowable.h"
+#endif
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
 #else
 # include "threads/none/threads.h"
 #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 "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
 
-/* linenumbertable_entry ******************************************************/
-
-/* Keep the type of line the same as the pointer type, otherwise we
-   run into alignment troubles (like on MIPS64). */
-
-typedef struct linenumbertable_entry linenumbertable_entry;
-
-struct linenumbertable_entry {
-       ptrint  line;               /* NOTE: see doc/inlining_stacktrace.txt for  */
-       u1     *pc;                 /*       special meanings of line and pc.     */
-};
 
 /* global variables ***********************************************************/
-
-#if !defined(USE_THREADS)
-stackframeinfo *_no_threads_stackframeinfo = NULL;
-#endif
-
-
-/* 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;
-
-       /* 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_findmethod(ra);
-               else
-#endif
-                       {
-#if defined(ENABLE_JIT)
-                               pv = md_codegen_findmethod(ra);
-#endif
-                       }
-       }
-
-       /* get methodinfo pointer from data segment */
-
-       m = *((methodinfo **) (pv + MethodPointer));
-
-       /* 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_findmethod(ra);
-
-       }
+#if !defined(ENABLE_THREADS)
+stackframeinfo_t *_no_threads_stackframeinfo = NULL;
 #endif
 
-       /* fill new stackframe info structure */
+CYCLES_STATS_DECLARE(stacktrace_overhead        ,100,1)
+CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace,40,5000)
+CYCLES_STATS_DECLARE(stacktrace_getClassContext ,40,5000)
+CYCLES_STATS_DECLARE(stacktrace_getCurrentClass ,40,5000)
+CYCLES_STATS_DECLARE(stacktrace_getStack        ,40,10000)
 
-       sfi->prev   = *psfi;
-       sfi->method = NULL;
-       sfi->pv     = pv;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-       sfi->xpc    = xpc;
 
-       /* store new stackframe info pointer */
+/* stacktrace_stackframeinfo_add ***********************************************
 
-       *psfi = sfi;
-}
-
-
-/* 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__)
-       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). */
@@ -217,25 +113,39 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
        if (pv == NULL) {
 #if defined(ENABLE_INTRP)
                if (opt_intrp)
-                       pv = codegen_findmethod(ra);
+                       pv = codegen_get_pv_from_pc(ra);
                else
 #endif
                        {
 #if defined(ENABLE_JIT)
-                               pv = md_codegen_findmethod(ra);
+# 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));
 
@@ -257,71 +167,79 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 # if defined(ENABLE_INTRP)
        }
 # endif
-#endif /* defined(ENABLE_JIT) */
+#endif
 
-       /* fill new stackframe info structure */
+       /* 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. */
 
-       sfi->prev   = *psfi;
-       sfi->method = NULL;
-       sfi->pv     = pv;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-       sfi->xpc    = xpc;
+       if (xpc == NULL) {
+               xpc = (void *) (((intptr_t) ra) - 1);
+       }
 
-       /* store new stackframe info pointer */
+       /* 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 stackframeinfo pointer. */
 
        *psfi = sfi;
+
+       /* set the native world flag for the current thread */
+       /* ATTENTION: This flag tells the GC how to treat this thread in case of
+          a collection. Set this flag _after_ a valid stackframe info was set. */
+
+       THREAD_NATIVEWORLD_ENTER;
 }
 
 
-/* stacktrace_create_native_stackframeinfo *************************************
+/* stacktrace_stackframeinfo_remove ********************************************
 
-   Creates a stackframe info structure for a native stub.
+   Remove the given stackframeinfo from the chain in the current
+   thread.
 
 *******************************************************************************/
 
-void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
-                                                                                        u1 *sp, u1 *ra)
+void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
 {
-       stackframeinfo **psfi;
-       methodinfo      *m;
+       stackframeinfo_t **psfi;
 
-       /* get methodinfo pointer from data segment */
+       /* clear the native world flag for the current thread */
+       /* ATTENTION: Clear this flag _before_ removing the stackframe info */
 
-       m = *((methodinfo **) (pv + MethodPointer));
+       THREAD_NATIVEWORLD_EXIT;
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
-
-       /* fill new stackframe info structure */
-
-       sfi->prev   = *psfi;
-       sfi->method = m;
-       sfi->pv     = NULL;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-       sfi->xpc    = NULL;
-
-       /* store new stackframe info pointer */
-
-       *psfi = sfi;
-}
-
-
-/* stacktrace_remove_stackframeinfo ********************************************
-
-   XXX
-
-*******************************************************************************/
-
-void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
-{
-       stackframeinfo **psfi;
+       psfi = &STACKFRAMEINFO;
 
-       /* get current stackframe info pointer */
-
-       psfi = STACKFRAMEINFO;
+#if !defined(NDEBUG)
+       if (opt_DebugStackFrameInfo) {
+               log_start();
+               log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+                                 sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
+               method_print(sfi->code->m);
+               log_print("]");
+               log_finish();
+       }
+#endif
 
        /* restore the old pointer */
 
@@ -329,755 +247,477 @@ void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
 }
 
 
-/* stacktrace_inline_arithmeticexception ***************************************
+/* stacktrace_entry_add ********************************************************
 
-   Creates an ArithemticException for inline stub.
+   Adds a new entry to the stacktrace buffer.
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                u1 *ra, u1 *xpc)
+static inline stacktracebuffer *stacktrace_entry_add(stacktracebuffer *stb, methodinfo *m, u2 line)
 {
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_arithmeticexception();
-
-       /* remove stackframeinfo */
+       stacktrace_entry *ste;
+       u4                stb_size_old;
+       u4                stb_size_new;
 
-       stacktrace_remove_stackframeinfo(&sfi);
+       /* check if we already reached the buffer capacity */
 
-       return o;
-}
+       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;
 
-/* stacktrace_inline_arrayindexoutofboundsexception ****************************
+               stb_size_new = stb_size_old +
+                                          sizeof(stacktrace_entry) * STACKTRACE_CAPACITY_INCREMENT;
 
-   Creates an ArrayIndexOutOfBoundsException for inline stub.
+               /* reallocate new memory */
 
-*******************************************************************************/
+               stb = DMREALLOC(stb, u1, stb_size_old, stb_size_new);
 
-java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
-                                                                                                                                       u1 *sp,
-                                                                                                                                       u1 *ra,
-                                                                                                                                       u1 *xpc,
-                                                                                                                                       s4 index)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
+               /* set new buffer capacity */
 
-       /* create stackframeinfo */
+               stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
+       }
 
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
+       /* insert the current entry */
 
-       /* create exception */
+       ste = &(stb->entries[stb->used]);
 
-       o = new_arrayindexoutofboundsexception(index);
+       ste->method     = m;
+       ste->linenumber = line;
 
-       /* remove stackframeinfo */
+       /* increase entries used count */
 
-       stacktrace_remove_stackframeinfo(&sfi);
+       stb->used += 1;
 
-       return o;
+       return stb;
 }
 
 
-/* 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 = new_arraystoreexception();
-
-       /* remove stackframeinfo */
+/* stacktrace_method_add *******************************************************
 
-       stacktrace_remove_stackframeinfo(&sfi);
+   Add stacktrace entries[1] for the given method to the stacktrace
+   buffer.
 
-       return o;
-}
-
-
-/* stacktrace_inline_classcastexception ****************************************
+   IN:
+       stb....stacktracebuffer to fill
+          sfi....current stackframeinfo
+   OUT:
+       stacktracebuffer after possible reallocation.
 
-   Creates an ClassCastException for inline stub.
+   [1] In case of inlined methods there may be more than one stacktrace
+       entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                               u1 *xpc)
+static inline stacktracebuffer *stacktrace_method_add(stacktracebuffer *stb, stackframeinfo_t *sfi)
 {
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_classcastexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
+       codeinfo   *code;
+       void       *pv;
+       void       *xpc;
+       methodinfo *m;
+       int32_t     linenumber;
 
-/* stacktrace_inline_nullpointerexception **************************************
+       /* Get values from the stackframeinfo. */
 
-   Creates an NullPointerException for inline stub.
-
-*******************************************************************************/
+       code = sfi->code;
+       pv   = sfi->pv;
+       xpc  = sfi->xpc;
 
-java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                 u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
+       m = code->m;
 
-       /* create stackframeinfo */
+       /* Skip builtin methods. */
 
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
+       if (m->flags & ACC_METHOD_BUILTIN)
+               return stb;
 
-       /* create exception */
+       /* Search the line number table. */
 
-       o = new_nullpointerexception();
+       linenumber = linenumbertable_linenumber_for_pc(&m, code, xpc);
 
-       /* remove stackframeinfo */
+       /* Add a new entry to the staktrace. */
 
-       stacktrace_remove_stackframeinfo(&sfi);
+       stb = stacktrace_entry_add(stb, m, linenumber);
 
-       return o;
+       return stb;
 }
 
 
-/* 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 */
+/* stacktrace_stackframeinfo_fill **********************************************
 
-       o = *exceptionptr;
+   Fill the temporary stackframeinfo structure with the values given
+   in sfi.
 
-       /* clear exception */
-
-       *exceptionptr = NULL;
-
-       /* resolve methodinfo pointer from exception object */
-
-       m = class_resolvemethod(o->vftbl->class,
-                                                       utf_fillInStackTrace,
-                                                       utf_void__java_lang_Throwable);
-
-       /* 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.
+   IN:
+       tmpsfi ... temporary stackframeinfo
+       sfi ...... stackframeinfo to be used in the next iteration
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                  u1 *ra, u1 *xpc)
+static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
 {
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
+       /* Sanity checks. */
 
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+       assert(tmpsfi != NULL);
+       assert(sfi != NULL);
 
-       /* create exception */
+       /* Fill the temporary stackframeinfo. */
 
-       o = new_arithmeticexception();
+       tmpsfi->code = sfi->code;
+       tmpsfi->pv   = sfi->pv;
+       tmpsfi->sp   = sfi->sp;
+       tmpsfi->ra   = sfi->ra;
+       tmpsfi->xpc  = sfi->xpc;
 
-       /* remove stackframeinfo */
+       /* Set the previous stackframe info of the temporary one to the
+          next in the chain. */
 
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
+       tmpsfi->prev = sfi->prev;
 }
 
 
-/* stacktrace_hardware_nullpointerexception ************************************
+/* stacktrace_stackframeinfo_next **********************************************
+
+   Walk the stack (or the stackframeinfo-chain) to the next method and
+   return the new stackframe values in the temporary stackframeinfo
+   passed.
 
-   Creates an NullPointerException for the SIGSEGV signal handler.
+   IN:
+       tmpsfi ... temporary stackframeinfo of current method
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                       u1 *ra, u1 *xpc)
+static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
 {
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
+       codeinfo         *code;
+       void             *pv;
+       void             *sp;
+       void             *ra;
+       void             *xpc;
+       uint32_t          framesize;
+       stackframeinfo_t *prevsfi;
 
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+       /* Sanity check. */
 
-       /* create exception */
+       assert(tmpsfi != NULL);
 
-       o = new_nullpointerexception();
+       /* Get values from the stackframeinfo. */
 
-       /* remove stackframeinfo */
+       code = tmpsfi->code;
+       pv   = tmpsfi->pv;
+       sp   = tmpsfi->sp;
+       ra   = tmpsfi->ra;
+       xpc  = tmpsfi->xpc;
 
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
+       /* Get the current stack frame size. */
 
+       framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
 
-/* stacktrace_add_entry ********************************************************
-
-   Adds a new entry to the stacktrace buffer.
-
-*******************************************************************************/
-
-static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
-{
-       stacktrace_entry *ste;
-
-       /* check if we already reached the buffer capacity */
+       /* 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 (stb->used >= stb->capacity) {
-               /* reallocate new memory */
-
-               stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
-                                                                stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
+       else
+# endif
+               {
+                       if (!code_is_leafmethod(code))
+                               ra = md_stacktrace_get_returnaddress(sp, framesize);
+               }
+#else
+       ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
+#endif
 
-               /* set new buffer capacity */
+       /* Get the PV for the parent Java method. */
 
-               stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
-       }
+#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
+               }
 
-       /* insert the current entry */
+       /* Get the codeinfo pointer for the parent Java method. */
 
-       ste = &(stb->entries[stb->used]);
+       code = code_get_codeinfo_for_pv(pv);
 
-       ste->method     = m;
-       ste->linenumber = line;
+       /* Calculate the SP for the parent Java method. */
 
-       /* increase entries used count */
+#if defined(ENABLE_INTRP)
+       if (opt_intrp)
+               sp = *(u1 **) (sp - framesize);
+       else
+#endif
+               {
+#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
+                       sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
+#elif defined(__SPARC_64__)
+                       /* already has the new sp */
+#else
+                       sp = (void *) (((intptr_t) sp) + framesize);
+#endif
+               }
 
-       stb->used += 1;
-}
+       /* If the new codeinfo pointer is NULL we reached a
+          asm_vm_call_method function.  In this case we get the next
+          values from the previous stackframeinfo in the chain.
+          Otherwise the new values have been calculated before. */
 
+       if (code == NULL) {
+               prevsfi = tmpsfi->prev;
 
-/* stacktrace_add_method_intern ************************************************
+               /* If the previous stackframeinfo in the chain is NULL we
+                  reached the top of the stacktrace.  We set code and prev to
+                  NULL to mark the end, which is checked in
+                  stacktrace_stackframeinfo_end_check. */
 
-   This function is used by stacktrace_add_method to search the line number
-   table for the line corresponding to a given pc. The function recurses for
-   inlined methods.
+               if (prevsfi == NULL) {
+                       tmpsfi->code = NULL;
+                       tmpsfi->prev = NULL;
+                       return;
+               }
 
-*******************************************************************************/
+               /* Fill the temporary stackframeinfo with the new values. */
 
-static bool stacktrace_add_method_intern(stacktracebuffer *stb, 
-                                                                                methodinfo *m, 
-                                                                                linenumbertable_entry *lntentry,
-                                                                                ptrint lntsize,
-                                                                                u1 *pc)
-{
-       linenumbertable_entry *lntinline;   /* special entry for inlined method */
-
-       assert(stb);
-       assert(lntentry);
-
-       /* Find the line number for the specified PC (going backwards
-          in the linenumber table). The linenumber table size is zero
-          in native stubs. */
-
-       for (; lntsize > 0; lntsize--, lntentry--) {
-
-               /* did we reach the current line? */
-
-               /* Note: In case of inlining this may actually compare the pc
-                  against a methodinfo *, yielding a non-sensical
-                  result. This is no problem, however, as we ignore such
-                  entries in the switch below. This way we optimize for the
-                  common case (ie. a real pc in lntentry->pc). */
-
-               if (pc >= lntentry->pc) {
-
-                       /* check for special inline entries (see
-                          doc/inlining_stacktrace.txt for details */
-
-                       if ((s4)lntentry->line < 0) {
-                               switch (lntentry->line) {
-                                       case -1: 
-                                               /* begin of inlined method (ie. INLINE_END
-                                                  instruction) */
-
-                                               lntinline = --lntentry;/* get entry with methodinfo * */
-                                               lntentry--;            /* skip the special entry      */
-                                               lntsize -= 2;
-
-                                               /* search inside the inlined method */
-                                               if (stacktrace_add_method_intern(
-                                                                       stb, 
-                                                                       (methodinfo*) lntinline->pc,
-                                                                       lntentry,
-                                                                       lntsize,
-                                                                       pc))
-                                               {
-                                                       /* the inlined method contained the pc */
-                                                       assert(lntinline->line <= -3);
-                                                       stacktrace_add_entry(stb, m, (-3) - lntinline->line);
-                                                       return true;
-                                               }
-                                               /* pc was not in inlined method, continue
-                                                  search.  Entries inside the inlined method
-                                                  will be skipped because their lntentry->pc
-                                                  is higher than pc.  */
-                                               break;
-
-                                       case -2: 
-                                               /* end of inlined method */
-                                               return false;
-
-                                       /* default: is only reached for an -3-line entry
-                                          after a skipped -2 entry. We can safely ignore
-                                          it and continue searching.  */
-                               }
-                       }
-                       else {
-                               /* found a normal entry */
-                               stacktrace_add_entry(stb, m, lntentry->line);
-                               return true;
-                       }
-               }
+               stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
+       }
+       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);
        }
-
-       /* not found */
-       return false;
 }
 
-/* stacktrace_add_method *******************************************************
 
-   Add stacktrace entries[1] for the given method to the stacktrace buffer.
+/* stacktrace_stackframeinfo_end_check *****************************************
 
-   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
+   Check if we reached the end of the stacktrace.
 
-   OUT:
-       true, if stacktrace entries were successfully created, false otherwise.
+   IN:
+       tmpsfi ... temporary stackframeinfo of current method
 
-   [1] In case of inlined methods there may be more than one stacktrace
-       entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
+   RETURN:
+       true .... the end is reached
+          false ... the end is not reached
 
 *******************************************************************************/
 
-static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
-                                                                 u1 *pc)
+static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
 {
-       ptrint                 lntsize;     /* size of line number table          */
-       u1                    *lntstart;    /* start of line number table         */
-       linenumbertable_entry *lntentry;    /* points to last entry in the table  */
-       codeinfo              *code;        /* compiled realization of method     */
-
-       /* get size of line number table */
+       /* Sanity check. */
 
-       lntsize  = *((ptrint *) (pv + LineNumberTableSize));
-       lntstart = *((u1 **)    (pv + LineNumberTableStart));
+       assert(tmpsfi != NULL);
 
-       /* Subtract the size of the line number entry of the structure,
-          since the line number table start points to the pc. */
-
-       lntentry = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
-
-       /* find the realization of the method the pc is in    */
-       /* XXX Note: This is preliminary. It would be cleaner */
-       /* to get the codeinfo * from the PV                  */
-
-       code = m->code;
-       while (1) {
-               if (!code) {
-#ifndef NDEBUG
-                       method_println(m);
-                       dolog("Could not find codeinfo for Current PC: %p",(void*)pc);
-#endif
-                       abort();
-               }
-
-               if (((ptrint)pc >= (ptrint)code->entrypoint)
-                               &&
-                       ( (pc - (u1*)code->entrypoint) < code->mcodelength ))
-               {
-                       /* found */
-                       break;
-               }
-
-               code = code->prev;
-       }
-
-       /* search the line number table */
-
-       if (stacktrace_add_method_intern(stb, m, lntentry, lntsize, pc))
+       if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL))
                return true;
 
-       /* If we get here, just add the entry with line number 0. */
-
-       stacktrace_add_entry(stb, m, 0);
-
-       return true;
+       return false;
 }
 
 
 /* stacktrace_create ***********************************************************
 
    Generates a stacktrace from the thread passed into a
-   stacktracebuffer.  The stacktracebuffer is allocated on the GC
-   heap.
+   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).
+
+   RETURN VALUE:
+      pointer to the stacktracebuffer, or
+      NULL if there is no stacktrace available for the
+      given thread.
 
 *******************************************************************************/
 
-stacktracebuffer *stacktrace_create(threadobject* thread)
+stacktracebuffer *stacktrace_create(stackframeinfo_t *sfi)
 {
        stacktracebuffer *stb;
-       stacktracebuffer *gcstb;
-       s4                dumpsize;
-       stackframeinfo   *sfi;
-       methodinfo       *m;
-       u1               *pv;
-       u1               *sp;
-       u4                framesize;
-       u1               *ra;
-       u1               *xpc;
-
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       /* prevent compiler warnings */
+       stackframeinfo_t  tmpsfi;
+       bool              skip_fillInStackTrace;
+       bool              skip_init;
 
-       pv = NULL;
-       sp = NULL;
-       ra = NULL;
+       skip_fillInStackTrace = true;
+       skip_init             = true;
 
-       /* create a stacktracebuffer in dump memory */
+       /* Create a stacktracebuffer in dump memory. */
 
        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). */
-
-#if defined(USE_THREADS)
-       sfi = thread->info._stackframeinfo;
-#else
-       sfi = _no_threads_stackframeinfo;
-#endif
-
-#define PRINTMETHODS 0
-
-#if PRINTMETHODS
-       printf("\n\nfillInStackTrace start:\n");
-       fflush(stdout);
-#endif
-
-       /* Loop while we have a method pointer (asm_calljavafunction has
-          NULL) or there is a stackframeinfo in the chain. */
-
-       m = NULL;
-
-       while (m || sfi) {
-               /* 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*). */
-
-#if defined(ENABLE_INTRP)
-                               if (opt_intrp)
-                                       pv = codegen_findmethod(ra);
-                               else
-#endif
-                                       {
-#if defined(ENABLE_JIT)
-                                               pv = md_codegen_findmethod(ra);
-#endif
-                                       }
-
-                               /* get methodinfo pointer from parent data segment */
-
-                               m = *((methodinfo **) (pv + MethodPointer));
-
-                       } 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(NDEBUG)
+       if (opt_DebugStackTrace) {
+               printf("\n\n---> stacktrace creation start (fillInStackTrace):\n");
+               fflush(stdout);
+       }
 #endif
 
-                               /* get methodinfo from current Java method */
-
-                               m = *((methodinfo **) (pv + MethodPointer));
-
-                               /* if m == NULL, this is a asm_calljavafunction call */
+       /* Put the data from the stackframeinfo into a temporary one. */
 
-                               if (m != NULL) {
-#if PRINTMETHODS
-                                       printf("ra=%p sp=%p, ", ra, sp);
-                                       method_print(m);
-                                       printf(": inline stub parent");
-                                       fflush(stdout);
-#endif
+       /* XXX This is not correct, but a workaround for threads-dump for
+          now. */
+/*     assert(sfi != NULL); */
+       if (sfi == NULL)
+               return NULL;
 
-#if defined(ENABLE_INTRP)
-                                       if (!opt_intrp) {
+       /* Iterate till we're done. */
+
+       for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+                stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+                stacktrace_stackframeinfo_next(&tmpsfi)) {
+#if !defined(NDEBUG)
+               /* Print current method information. */
+
+               if (opt_DebugStackTrace) {
+                       log_start();
+                       log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+                                         tmpsfi.code->m, tmpsfi.pv, tmpsfi.sp, tmpsfi.ra,
+                                         tmpsfi.xpc);
+                       method_print(tmpsfi.code->m);
+                       log_print("]");
+                       log_finish();
+               }
 #endif
 
-                                       /* add the method to the stacktrace */
+               /* This logic is taken from
+                  hotspot/src/share/vm/classfile/javaClasses.cpp
+                  (java_lang_Throwable::fill_in_stack_trace). */
 
-                                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
+               if (skip_fillInStackTrace == true) {
+                       /* Check "fillInStackTrace" only once, so we negate the
+                          flag after the first time check. */
 
-                                       /* get the current stack frame size */
+#if defined(WITH_CLASSPATH_GNU)
+                       /* For GNU Classpath we also need to skip
+                          VMThrowable.fillInStackTrace(). */
 
-                                       framesize = *((u4 *) (pv + FrameSize));
-
-#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
 
-                                       /* set stack pointer to stackframe of parent Java */
-                                       /* function of the current Java function */
-
-#if defined(__I386__) || defined (__X86_64__)
-                                       sp += framesize + SIZEOF_VOID_P;
-#else
-                                       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_JIT)
-                                       pv = md_codegen_findmethod(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. */
 
-                                       m = *((methodinfo **) (pv + MethodPointer));
+               if (skip_init == true) {
+                       if (tmpsfi.code->m->name == utf_init) {
+/*                             throwable->is_a(method->method_holder())) { */
+                               continue;
+                       }
+                       else {
+                               /* If no "Throwable.init()" method found, we stop
+                                  checking it next time. */
 
-#if defined(ENABLE_INTRP)
-                                       }
-#endif
-                               }
-#if PRINTMETHODS
-                               else {
-                                       printf("ra=%p sp=%p, ", ra, sp);
-                                       printf("asm_calljavafunction\n");
-                                       fflush(stdout);
-                               }
-#endif
+                               skip_init = false;
                        }
+               }
 
-                       /* get previous stackframeinfo in the chain */
+               /* Add this method to the stacktrace. */
 
-                       sfi = sfi->prev;
+               stb = stacktrace_method_add(stb, &tmpsfi);
+       }
 
-               } else {
-#if PRINTMETHODS
-                       printf("ra=%p sp=%p, ", ra, sp);
-                       method_print(m);
-                       printf(": JIT");
-                       fflush(stdout);
+#if !defined(NDEBUG)
+       if (opt_DebugStackTrace) {
+               printf("---> stacktrace creation finished.\n\n");
+               fflush(stdout);
+       }
 #endif
 
-                       /* JIT method found, add it to the stacktrace (we subtract
-                          1 from the return address since it points the the
-                          instruction after call). */
+       /* return the stacktracebuffer */
 
-                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
+       if (stb->used == 0)
+               return NULL;
+       else
+               return stb;
+}
 
-                       /* get the current stack frame size */
 
-                       framesize = *((u4 *) (pv + FrameSize));
+/* stacktrace_fillInStackTrace *************************************************
 
-#if PRINTMETHODS
-                       printf(", framesize=%d\n", framesize);
-                       fflush(stdout);
-#endif
+   Generate a stacktrace from the current thread for
+   java.lang.VMThrowable.fillInStackTrace.
 
-                       /* 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
+java_handle_bytearray_t *stacktrace_fillInStackTrace(void)
+{
+       stacktracebuffer        *stb;
+       java_handle_bytearray_t *ba;
+       s4                       ba_size;
+       s4                       dumpsize;
+       CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
 
-                       /* get data segment and methodinfo pointer from parent method */
+       /* mark start of dump memory area */
 
-#if defined(ENABLE_INTRP)
-                       if (opt_intrp)
-                               pv = codegen_findmethod(ra);
-                       else
-#endif
-                               {
-#if defined(ENABLE_JIT)
-                                       pv = md_codegen_findmethod(ra);
-#endif
-                               }
+       dumpsize = dump_size();
 
-                       m = *((methodinfo **) (pv + MethodPointer));
+       /* create a stacktrace from the current thread */
 
-                       /* walk the stack */
+       stb = stacktrace_create(STACKFRAMEINFO);
 
-#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 (stb == NULL)
+               goto return_NULL;
 
        /* allocate memory from the GC heap and copy the stacktrace buffer */
+       /* ATTENTION: use a bytearray for this to not confuse the GC */
 
-       gcstb = GCNEW(stacktracebuffer);
-
-       if (gcstb == NULL) {
-               dump_release(dumpsize);
-
-               return NULL;
-       }
+       ba_size = sizeof(stacktracebuffer) +
+                 sizeof(stacktrace_entry) * stb->used -
+                 sizeof(stacktrace_entry) * STACKTRACE_CAPACITY_DEFAULT;
+       ba = builtin_newarray_byte(ba_size);
 
-       gcstb->capacity = stb->capacity;
-       gcstb->used     = stb->used;
-       gcstb->entries  = GCMNEW(stacktrace_entry, stb->used);
+       if (ba == NULL)
+               goto return_NULL;
 
-       if (gcstb->entries == NULL) {
-               dump_release(dumpsize);
-
-               return NULL;
-       }
-
-       MCOPY(gcstb->entries, stb->entries, stacktrace_entry, stb->used);
+       MCOPY(LLNI_array_data(ba), stb, u1, ba_size);
 
        /* release dump memory */
 
        dump_release(dumpsize);
 
-       /* return the stacktracebuffer */
-
-       return gcstb;
-}
-
-
-/* stacktrace_fillInStackTrace *************************************************
-
-   Generate a stacktrace from the current thread for
-   java.lang.VMThrowable.fillInStackTrace.
-
-*******************************************************************************/
+       CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+                                                                  stacktrace_overhead)
+       return ba;
 
-stacktracebuffer *stacktrace_fillInStackTrace(void)
-{
-       stacktracebuffer *stb;
-
-       /* create a stacktrace from the current thread */
+return_NULL:
+       dump_release(dumpsize);
 
-       stb = stacktrace_create(THREADOBJECT);
+       CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+                                                                  stacktrace_overhead)
 
-       return stb;
+       return NULL;
 }
 
 
@@ -1091,17 +731,26 @@ stacktracebuffer *stacktrace_fillInStackTrace(void)
 
 *******************************************************************************/
 
-java_objectarray *stacktrace_getClassContext(void)
+java_handle_objectarray_t *stacktrace_getClassContext(void)
 {
-       stacktracebuffer  *stb;
-       stacktrace_entry  *ste;
-       java_objectarray  *oa;
-       s4                 oalength;
-       s4                 i;
+       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 */
+
+       dumpsize = dump_size();
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
+       stb = stacktrace_create(STACKFRAMEINFO);
+
+       if (stb == NULL)
+               goto return_NULL;
 
        /* calculate the size of the Class array */
 
@@ -1109,26 +758,18 @@ java_objectarray *stacktrace_getClassContext(void)
                if (stb->entries[i].method != NULL)
                        oalength++;
 
+       /* The first entry corresponds to the method whose implementation */
+       /* calls stacktrace_getClassContext. We remove that entry.        */
+
        ste = &(stb->entries[0]);
        ste++;
        oalength--;
 
-       /* XXX document me */
-
-       if (oalength > 0) {
-               if (ste->method &&
-                       (ste->method->class == class_java_lang_SecurityManager)) {
-                       ste++;
-                       oalength--;
-               }
-       }
-
        /* allocate the Class array */
 
        oa = builtin_anewarray(oalength, class_java_lang_Class);
-
        if (!oa)
-               return NULL;
+               goto return_NULL;
 
        /* fill the Class array from the stacktracebuffer */
 
@@ -1138,10 +779,23 @@ 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 */
+
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getClassContext)
+
        return oa;
+
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getClassContext)
+
+       return NULL;
 }
 
 
@@ -1162,16 +816,26 @@ java_objectarray *stacktrace_getClassContext(void)
 
 *******************************************************************************/
 
+#if defined(ENABLE_JAVASE)
 classinfo *stacktrace_getCurrentClass(void)
 {
        stacktracebuffer  *stb;
        stacktrace_entry  *ste;
        methodinfo        *m;
        s4                 i;
+       s4                 dumpsize;
+       CYCLES_STATS_DECLARE_AND_START
+
+       /* mark start of dump memory area */
+
+       dumpsize = dump_size();
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
+       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
           class */
@@ -1183,38 +847,63 @@ classinfo *stacktrace_getCurrentClass(void)
                        continue;
 
                if (m->class == class_java_security_PrivilegedAction)
-                       return NULL;
+                       goto return_NULL;
+
+               if (m->class != NULL) {
+                       dump_release(dumpsize);
+
+                       CYCLES_STATS_END(stacktrace_getCurrentClass)
 
-               if (m->class != NULL)
                        return m->class;
+               }
        }
 
        /* no Java method found on the stack */
 
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getCurrentClass)
+
        return NULL;
 }
+#endif /* ENABLE_JAVASE */
 
 
 /* stacktrace_getStack *********************************************************
 
    Create a 2-dimensional array for java.security.VMAccessControler.
 
+   RETURN VALUE:
+      the arrary, or
+         NULL if an exception has been thrown
+
 *******************************************************************************/
 
-java_objectarray *stacktrace_getStack(void)
+#if defined(ENABLE_JAVASE)
+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;
+       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 */
+
+       dumpsize = dump_size();
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
+       stb = stacktrace_create(STACKFRAMEINFO);
+
+       if (stb == NULL)
+               goto return_NULL;
 
        /* get the first stacktrace entry */
 
@@ -1224,42 +913,55 @@ java_objectarray *stacktrace_getStack(void)
 
        oa = builtin_anewarray(2, arrayclass_java_lang_Object);
 
-       if (!oa)
-               return NULL;
+       if (oa == NULL)
+               goto return_NULL;
 
        classes = builtin_anewarray(stb->used, class_java_lang_Class);
 
-       if (!classes)
-               return NULL;
+       if (classes == NULL)
+               goto return_NULL;
 
        methodnames = builtin_anewarray(stb->used, class_java_lang_String);
 
-       if (!methodnames)
-               return NULL;
+       if (methodnames == NULL)
+               goto return_NULL;
 
        /* 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;
 
-               if (!str)
-                       return NULL;
+               string = javastring_new(ste->method->name);
 
-               methodnames->data[i] = (java_objectheader *) str;
+               if (string == NULL)
+                       goto return_NULL;
+
+               array_objectarray_element_set(methodnames, i, string);
        }
 
        /* return the 2-dimensional array */
 
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getStack)
+
        return oa;
+
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getStack)
+
+       return NULL;
 }
+#endif /* ENABLE_JAVASE */
 
 
 /* stacktrace_print_trace_from_buffer ******************************************
@@ -1270,7 +972,7 @@ java_objectarray *stacktrace_getStack(void)
 
 *******************************************************************************/
 
-static void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
+void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
 {
        stacktrace_entry *ste;
        methodinfo       *m;
@@ -1282,17 +984,17 @@ static void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
                m = ste->method;
 
                printf("\tat ");
-               utf_display_classname(m->class->name);
+               utf_display_printable_ascii_classname(m->class->name);
                printf(".");
-               utf_display(m->name);
-               utf_display(m->descriptor);
+               utf_display_printable_ascii(m->name);
+               utf_display_printable_ascii(m->descriptor);
 
                if (m->flags & ACC_NATIVE) {
                        puts("(Native Method)");
 
                } else {
                        printf("(");
-                       utf_display(m->class->sourcefile);
+                       utf_display_printable_ascii(m->class->sourcefile);
                        printf(":%d)\n", (u4) ste->linenumber);
                }
        }
@@ -1303,80 +1005,59 @@ static void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
 }
 
 
-/* stacktrace_dump_trace *******************************************************
+/* stacktrace_print_exception **************************************************
 
-   This method is call from signal_handler_sigusr1 to dump the
-   stacktrace of the current thread to stdout.
+   Print the stacktrace of a given exception. More or less a wrapper
+   to stacktrace_print_trace_from_buffer.
 
 *******************************************************************************/
 
-void stacktrace_dump_trace(void)
+void stacktrace_print_exception(java_handle_t *h)
 {
-       stacktracebuffer *stb;
+       java_lang_Throwable     *t;
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThrowable   *vmt;
+#endif
+       java_handle_bytearray_t *ba;
+       stacktracebuffer        *stb;
 
-#if 0
-       /* get methodinfo pointer from data segment */
+       t = (java_lang_Throwable *) h;
 
-       m = *((methodinfo **) (pv + MethodPointer));
+       if (t == NULL)
+               return;
 
-       /* get current stackframe info pointer */
+       /* now print the stacktrace */
 
-       psfi = STACKFRAMEINFO;
+#if defined(WITH_CLASSPATH_GNU)
 
-       /* fill new stackframe info structure */
+       LLNI_field_get_ref(t,   vmState, vmt);
+       LLNI_field_get_ref(vmt, vmData,  ba);
 
-       sfi->prev   = *psfi;
-       sfi->method = NULL;
-       sfi->pv     = NULL;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
 
-       /* store new stackframe info pointer */
+       LLNI_field_get_ref(t, backtrace, ba);
 
-       *psfi = sfi;
+#else
+# error unknown classpath configuration
 #endif
 
-       /* create a stacktrace for the current thread */
-
-       stb = stacktrace_create(THREADOBJECT);
+       assert(ba);
+       stb = (stacktracebuffer *) LLNI_array_data(ba);
 
-       /* print stacktrace */
-
-       if (stb) {
-               stacktrace_print_trace_from_buffer(stb);
-
-       } else {
-               puts("\t<<No stacktrace available>>");
-               fflush(stdout);
-       }
+       stacktrace_print_trace_from_buffer(stb);
 }
 
 
-/* stacktrace_print_trace ******************************************************
-
-   Print the stacktrace of a given exception. More or less a wrapper
-   to stacktrace_print_trace_from_buffer.
-
-*******************************************************************************/
-
-void stacktrace_print_trace(java_objectheader *xptr)
+#if defined(ENABLE_CYCLES_STATS)
+void stacktrace_print_cycles_stats(FILE *file)
 {
-       java_lang_Throwable   *t;
-       java_lang_VMThrowable *vmt;
-       stacktracebuffer      *stb;
-
-       t = (java_lang_Throwable *) xptr;
-
-       if (t == NULL)
-               return;
-
-       /* now print the stacktrace */
-
-       vmt = t->vmState;
-       stb = (stacktracebuffer *) vmt->vmData;
-
-       stacktrace_print_trace_from_buffer(stb);
+       CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead,file);
+       CYCLES_STATS_PRINT(stacktrace_fillInStackTrace,file);
+       CYCLES_STATS_PRINT(stacktrace_getClassContext ,file);
+       CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,file);
+       CYCLES_STATS_PRINT(stacktrace_getStack        ,file);
 }
+#endif
 
 
 /*