* Removed all Id tags.
[cacao.git] / src / vm / jit / stacktrace.c
index ada7d6a8fa1e88023608a95a39e71dffea2388c1..98e96d149af0121bbf9933d24e52524131b7824b 100644 (file)
@@ -1,9 +1,9 @@
-/* src/vm/jit/stacktrace.c - machine independet stacktrace system
+/* src/vm/jit/stacktrace.c - machine independent stacktrace system
 
-   Copyright (C) 1996-2005 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
+   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
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Joseph Wenninger
-
-   Changes: Christian Thalinger
-
-   $Id: stacktrace.c 3652 2005-11-11 11:14:31Z twisti $
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
 
+#include "config.h"
+
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "config.h"
+#include "vm/types.h"
+
+#include "mm/gc-common.h"
+#include "mm/memory.h"
 
-#include "mm/boehm.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(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/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/tables.h"
+#include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen.inc.h"
+#include "vm/jit/codegen-common.h"
 #include "vm/jit/methodheader.h"
 
-
-/* lineNumberTableEntry *******************************************************/
-
-/* Keep the type of line the same as the pointer type, otherwise we run into  */
-/* alignment troubles (like on MIPS64).                                       */
-
-typedef struct lineNumberTableEntry {
-       ptrint  line;
-       u1     *pc;
-} lineNumberTableEntry;
-
-
-typedef struct lineNumberTableEntryInlineBegin {
-       /* this should have the same layout and size as the lineNumberTableEntry */
-       ptrint      lineNrOuter;
-       methodinfo *method;
-} lineNumberTableEntryInlineBegin;
-
-#ifndef ENABLE_JVMTI
-typedef bool(*CacaoStackTraceCollector)(void **, stackTraceBuffer*);
-#endif
-
-#define BLOCK_INITIALSIZE 40
-#define BLOCK_SIZEINCREMENT 40
+#include "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
 
 
 /* global variables ***********************************************************/
-
-#if !defined(USE_THREADS)
+#if !defined(ENABLE_THREADS)
 stackframeinfo *_no_threads_stackframeinfo = NULL;
 #endif
 
+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)
+
 
 /* stacktrace_create_stackframeinfo ********************************************
 
@@ -100,36 +90,51 @@ stackframeinfo *_no_threads_stackframeinfo = NULL;
 *******************************************************************************/
 
 #if defined(ENABLE_INTRP)
-void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv,
-                                                                         u1 *sp, functionptr ra)
+void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
+                                                                         u1 *ra)
 {
        stackframeinfo **psfi;
        methodinfo      *m;
+       codeinfo        *code;
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        /* if we don't have pv handy */
 
-       if (pv == NULL)
-               pv = (u1 *) (ptrint) codegen_findmethod(ra);
+       if (pv == NULL) {
+#if defined(ENABLE_INTRP)
+               if (opt_intrp)
+                       pv = codegen_get_pv_from_pc(ra);
+               else
+#endif
+                       {
+#if defined(ENABLE_JIT)
+                               pv = md_codegen_get_pv_from_pc(ra);
+#endif
+                       }
+       }
+
+       /* get codeinfo pointer from data segment */
+
+       code = *((codeinfo **) (pv + CodeinfoPointer));
 
-       /* get methodinfo pointer from data segment */
+       /* For asm_vm_call_method the codeinfo pointer is NULL. */
 
-       m = *((methodinfo **) (pv + MethodPointer));
+       m = (code == NULL) ? NULL : code->m;
 
        /* fill new stackframe info structure */
 
-       sfi->prev = *psfi;
+       sfi->prev   = *psfi;
        sfi->method = m;
-       sfi->pv = pv;
-       sfi->sp = sp;
-       sfi->ra = ra;
+       sfi->pv     = pv;
+       sfi->sp     = sp;
+       sfi->ra     = ra;
 
-       /* xpc is the same as ra, but is required in fillInStackTrace */
+       /* xpc is the same as ra, but is required in stacktrace_create */
 
-       sfi->xpc = ra;
+       sfi->xpc    = ra;
 
        /* store new stackframe info pointer */
 
@@ -137,46 +142,6 @@ void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 }
 #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, functionptr ra,
-                                                                                        functionptr 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 = (u1 *) (ptrint) codegen_findmethod(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 *************************************
 
@@ -186,33 +151,52 @@ void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 *******************************************************************************/
 
 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
-                                                                                        u1 *sp, functionptr ra,
-                                                                                        functionptr xpc)
+                                                                                        u1 *sp, u1 *ra, u1 *xpc)
 {
        stackframeinfo **psfi;
-#if !defined(__I386__) && !defined(__X86_64__)
+#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
        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). */
 
-       if (pv == NULL)
-               pv = (u1 *) (ptrint) codegen_findmethod(ra);
-
+       if (pv == NULL) {
 #if defined(ENABLE_INTRP)
+               if (opt_intrp)
+                       pv = codegen_get_pv_from_pc(ra);
+               else
+#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
+                       }
+       }
+
+#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__)
+# endif
+# 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));
 
@@ -231,18 +215,19 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
                        ra = md_stacktrace_get_returnaddress(sp, framesize);
                }
 # endif
-#if defined(ENABLE_INTRP)
+# if defined(ENABLE_INTRP)
        }
-#endif
+# endif
+#endif /* defined(ENABLE_JIT) */
 
        /* fill new stackframe info structure */
 
-       sfi->prev = *psfi;
+       sfi->prev   = *psfi;
        sfi->method = NULL;
-       sfi->pv = pv;
-       sfi->sp = sp;
-       sfi->ra = ra;
-       sfi->xpc = xpc;
+       sfi->pv     = pv;
+       sfi->sp     = sp;
+       sfi->ra     = ra;
+       sfi->xpc    = xpc;
 
        /* store new stackframe info pointer */
 
@@ -257,27 +242,32 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 *******************************************************************************/
 
 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
-                                                                                        u1 *sp, functionptr ra)
+                                                                                        u1 *sp, u1 *ra)
 {
        stackframeinfo **psfi;
        methodinfo      *m;
+       codeinfo        *code;
+
+       /* get codeinfo pointer from data segment */
 
-       /* get methodinfo pointer from data segment */
+       code = *((codeinfo **) (pv + CodeinfoPointer));
 
-       m = *((methodinfo **) (pv + MethodPointer));
+       /* For asm_vm_call_method the codeinfo pointer is NULL. */
+
+       m = (code == NULL) ? NULL : code->m;
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        /* fill new stackframe info structure */
 
-       sfi->prev = *psfi;
+       sfi->prev   = *psfi;
        sfi->method = m;
-       sfi->pv = NULL;
-       sfi->sp = sp;
-       sfi->ra = ra;
-       sfi->xpc = NULL;
+       sfi->pv     = NULL;
+       sfi->sp     = sp;
+       sfi->ra     = ra;
+       sfi->xpc    = NULL;
 
        /* store new stackframe info pointer */
 
@@ -287,7 +277,7 @@ void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 
 /* stacktrace_remove_stackframeinfo ********************************************
 
-   XXX
+   Remove the topmost stackframeinfo in the current thread.
 
 *******************************************************************************/
 
@@ -297,7 +287,7 @@ void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        /* restore the old pointer */
 
@@ -305,436 +295,109 @@ void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
 }
 
 
-/* stacktrace_inline_arithmeticexception ***************************************
-
-   Creates an ArithemticException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                functionptr ra,
-                                                                                                                functionptr xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_arithmeticexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_arrayindexoutofboundsexception ****************************
-
-   Creates an ArrayIndexOutOfBoundsException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
-                                                                                                                                       u1 *sp,
-                                                                                                                                       functionptr ra,
-                                                                                                                                       functionptr 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,
-                                                                                                                functionptr ra,
-                                                                                                                functionptr 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_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_classcastexception ****************************************
-
-   Creates an ClassCastException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp,
-                                                                                                               functionptr ra,
-                                                                                                               functionptr xpc)
-{
-       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;
-}
-
-
-/* stacktrace_inline_nullpointerexception **************************************
-
-   Creates an NullPointerException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                 functionptr ra,
-                                                                                                                 functionptr xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_nullpointerexception();
-
-       /* 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,
-                                                                                                                  functionptr ra,
-                                                                                                                  functionptr 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 ************************************
+/* stacktrace_add_entry ********************************************************
 
-   Creates an NullPointerException for the SIGSEGV signal handler.
+   Adds a new entry to the stacktrace buffer.
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                       functionptr ra,
-                                                                                                                       functionptr xpc)
+static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
 {
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_nullpointerexception();
+       stacktrace_entry *ste;
 
-       /* remove stackframeinfo */
+       /* check if we already reached the buffer capacity */
 
-       stacktrace_remove_stackframeinfo(&sfi);
+       if (stb->used >= stb->capacity) {
+               /* reallocate new memory */
 
-       return o;
-}
-
-
-/* stacktrace_inline_fillInStackTrace ******************************************
+               stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
+                                                                stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
 
-   Fills in the correct stacktrace into an existing exception object
-   (this one is for inline exception stubs).
+               /* set new buffer capacity */
 
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp,
-                                                                                                         functionptr ra,
-                                                                                                         functionptr xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-       methodinfo        *m;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* get exception */
-
-       o = *exceptionptr;
-
-       /* clear exception */
-
-       *exceptionptr = NULL;
-
-       /* resolve methodinfo pointer from exception object */
-
-       m = class_resolvemethod(o->vftbl->class,
-                                                       utf_fillInStackTrace,
-                                                       utf_void__java_lang_Throwable);
+               stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
+       }
 
-       /* call function */
+       /* insert the current entry */
 
-       asm_calljavafunction(m, o, NULL, NULL, NULL);
+       ste = &(stb->entries[stb->used]);
 
-       /* remove stackframeinfo */
+       ste->method     = m;
+       ste->linenumber = line;
 
-       stacktrace_remove_stackframeinfo(&sfi);
+       /* increase entries used count */
 
-       return o;
+       stb->used += 1;
 }
 
 
-/* addEntry ********************************************************************
-
-   XXX
+/* stacktrace_add_method *******************************************************
 
-*******************************************************************************/
-
-static void addEntry(stackTraceBuffer *buffer, methodinfo *method, u2 line)
-{
-       if (buffer->size > buffer->full) {
-               stacktraceelement *tmp = &(buffer->start[buffer->full]);
-
-               tmp->method = method;
-               tmp->linenumber = line;
-               buffer->full = buffer->full + 1;
-
-       } else {
-               stacktraceelement *newBuffer;
-
-               newBuffer =
-                       (stacktraceelement *) malloc((buffer->size + BLOCK_SIZEINCREMENT) *
-                                                                                sizeof(stacktraceelement));
+   Add stacktrace entries[1] for the given method to the stacktrace buffer.
 
-               if (newBuffer == 0) {
-                       log_text("OOM during stacktrace creation");
-                       assert(0);
-               }
-
-               memcpy(newBuffer, buffer->start, buffer->size * sizeof(stacktraceelement));
-               if (buffer->needsFree)
-                       free(buffer->start);
-
-               buffer->start = newBuffer;
-               buffer->size = buffer->size + BLOCK_SIZEINCREMENT;
-               buffer->needsFree = 1;
-
-               addEntry(buffer, method, line);
-       }
-}
+   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
 
+   OUT:
+       true, if stacktrace entries were successfully created, false otherwise.
 
-/* stacktrace_fillInStackTrace_methodRecursive *********************************
-
-   XXX
+   [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_fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,
-                                                                                                               methodinfo *m,
-                                                                                                               lineNumberTableEntry *lntentry,
-                                                                                                               s4 lntsize,
-                                                                                                               u1 *pc)
+static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
+                                                                 u1 *pc)
 {
-#if 0
-       lineNumberTableEntryInlineBegin *lntinline;
-#endif
-
-       /* find the line number for the specified pc (going backwards) */
-
-       for (; lntsize > 0; lntsize--, lntentry--) {
-               /* did we reach the current line? */
-
-               if (pc >= lntentry->pc) {
-                       /* check for special inline entries */
-
-                       switch (lntentry->line) {
-#if 0
-                       /* XXX TWISTI we have to think about this inline stuff again */
+       codeinfo *code;                     /* compiled realization of method     */
+       s4        linenumber;
 
-                       case -1: /* begin of inlined method */
-                               lntinline = (lineNumberTableEntryInlineBegin *) (--lntentry);
-                               lntentry++;
-                               lntsize--; lntsize--;
-                               if (stacktrace_fillInStackTrace_methodRecursive(buffer,
-                                                                                                                               ilStart->method,
-                                                                                                                               ent,
-                                                                                                                               &ent,
-                                                                                                                               &ahead,
-                                                                                                                               pc)) {
-                                       addEntry(buffer, m, ilStart->lineNrOuter);
+       /* find the realization of the method the pc is in */
 
-                                       return true;
-                               }
-                               break;
-
-                       case -2: /* end of inlined method */
-                               *entry = ent;
-                               *entriesAhead = ahead;
-                               return false;
-                               break;
-#endif
-
-                       default:
-                               addEntry(buffer, m, lntentry->line);
-                               return true;
-                       }
-               }
-       }
+       code = *((codeinfo **) (pv + CodeinfoPointer));
 
-       /* check if we are before the actual JIT code */
+       /* search the line number table */
 
-       if ((ptrint) pc < (ptrint) m->entrypoint) {
-               dolog("Current pc before start of code: %p < %p", pc, m->entrypoint);
-               assert(0);
-       }
+       linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
 
-       /* otherwise just add line 0 */
+       /* now add a new entry to the staktrace */
 
-       addEntry(buffer, m, 0);
+       stacktrace_add_entry(stb, m, linenumber);
 
        return true;
 }
 
 
-/* stacktrace_fillInStackTrace_method ******************************************
-
-   XXX
-
-*******************************************************************************/
-
-static void stacktrace_fillInStackTrace_method(stackTraceBuffer *buffer,
-                                                                                          methodinfo *method, u1 *pv,
-                                                                                          u1 *pc)
-{
-       ptrint                lntsize;      /* size of line number table          */
-       u1                   *lntstart;     /* start of line number table         */
-       lineNumberTableEntry *lntentry;     /* points to last entry in the table  */
-
-       /* get size of line number table */
-
-       lntsize  = *((ptrint *) (pv + LineNumberTableSize));
-       lntstart = *((u1 **)    (pv + LineNumberTableStart));
-
-       /* subtract the size of the line number entry of the structure, since the */
-       /* line number table start points to the pc */
-
-       lntentry = (lineNumberTableEntry *) (lntstart - SIZEOF_VOID_P);
+/* stacktrace_create ***********************************************************
 
-       if (lntsize == 0) {
-               /* this happens when an exception is thrown in the native stub */
+   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).
 
-               addEntry(buffer, method, 0);
-
-       } else {
-               if (!stacktrace_fillInStackTrace_methodRecursive(buffer,
-                                                                                                                method,
-                                                                                                                lntentry,
-                                                                                                                lntsize,
-                                                                                                                pc)) {
-                       log_text("Trace point not found in suspected method");
-                       assert(0);
-               }
-       }
-}
-
-
-/* cacao_stacktrace_fillInStackTrace *******************************************
-
-   XXX
+   RETURN VALUE:
+      pointer to the stacktracebuffer, or
+      NULL if there is no stacktrace available for the
+      given thread.
 
 *******************************************************************************/
-#ifdef ENABLE_JVMTI
-bool cacao_stacktrace_fillInStackTrace(void **target,
-                                                                          CacaoStackTraceCollector coll,
-                                                                          threadobject* thread)
-#else
-static bool cacao_stacktrace_fillInStackTrace(void **target,
-                                                                          CacaoStackTraceCollector coll)
-#endif
 
+stacktracebuffer *stacktrace_create(stackframeinfo *sfi)
 {
-       stacktraceelement primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)];
-       stackTraceBuffer  buffer;
-       stackframeinfo   *sfi;
+       stacktracebuffer *stb;
        methodinfo       *m;
+       codeinfo         *code;
        u1               *pv;
        u1               *sp;
        u4                framesize;
-       functionptr       ra;
-       functionptr       xpc;
-       bool              result;
+       u1               *ra;
+       u1               *xpc;
 
        /* prevent compiler warnings */
 
@@ -742,30 +405,13 @@ static bool cacao_stacktrace_fillInStackTrace(void **target,
        sp = NULL;
        ra = NULL;
 
-       /* In most cases this should be enough -> one malloc less. I don't think  */
-       /* temporary data should be allocated with the GC, only the result.       */
-
-       buffer.needsFree = 0;
-       buffer.start = primaryBlock;
-       buffer.size = BLOCK_INITIALSIZE; /*  *sizeof(stacktraceelement); */
-       buffer.full = 0;
-
-       /* the first element in the stackframe chain must always be a native      */
-       /* stackframeinfo (VMThrowable.fillInStackTrace is a native function)     */
+       /* create a stacktracebuffer in dump memory */
 
-#ifdef ENABLE_JVMTI
-       if (thread == NULL) 
-               sfi = *STACKFRAMEINFO; /* invocation from Throwable */
-       else
-               sfi = thread->info._stackframeinfo; /* invocation from JVMTI */
-#else
-       sfi = *STACKFRAMEINFO;
-#endif
+       stb = DNEW(stacktracebuffer);
 
-       if (!sfi) {
-               *target = NULL;
-               return true;
-       }
+       stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
+       stb->used     = 0;
+       stb->entries  = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
 
 #define PRINTMETHODS 0
 
@@ -774,15 +420,15 @@ static bool cacao_stacktrace_fillInStackTrace(void **target,
        fflush(stdout);
 #endif
 
-       /* loop while we have a method pointer (asm_calljavafunction has NULL) or */
-       /* there is a stackframeinfo in the chain                                 */
+       /* 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                                                            */
+       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 */
@@ -795,32 +441,45 @@ static bool cacao_stacktrace_fillInStackTrace(void **target,
                                ra = sfi->ra;
 
                                if (m)
-                                       addEntry(&buffer, m, 0);
+                                       stacktrace_add_entry(stb, m, 0);
 
 #if PRINTMETHODS
                                printf("ra=%p sp=%p, ", ra, sp);
-                               utf_display_classname(m->class->name);
-                               printf(".");
-                               utf_display(m->name);
-                               utf_display(m->descriptor);
+                               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*) */
+                               /* This is an native stub stackframe info, so we can
+                                  get the parent pv from the return address
+                                  (ICMD_INVOKE*). */
 
-                               pv = (u1 *) (ptrint) codegen_findmethod(ra);
+#if defined(ENABLE_INTRP)
+                               if (opt_intrp)
+                                       pv = codegen_get_pv_from_pc(ra);
+                               else
+#endif
+                                       {
+#if defined(ENABLE_JIT)
+                                               pv = md_codegen_get_pv_from_pc(ra);
+#endif
+                                       }
 
                                /* get methodinfo pointer from parent data segment */
 
-                               m = *((methodinfo **) (pv + MethodPointer));
+                               code = *((codeinfo **) (pv + CodeinfoPointer));
+
+                               /* For asm_vm_call_method the codeinfo pointer is
+                                  NULL. */
+
+                               m = (code == NULL) ? NULL : code->m;
 
                        } else {
-                               /* Inline stackframe infos are special: they have a xpc of    */
-                               /* the actual exception position and the return address saved */
-                               /* since an inline stackframe info can also be in a leaf      */
-                               /* method (no return address saved on stack!!!).              */
-                               /* ATTENTION: This one is also for hardware exceptions!!!     */
+                               /* 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 */
 
@@ -838,17 +497,19 @@ static bool cacao_stacktrace_fillInStackTrace(void **target,
 
                                /* get methodinfo from current Java method */
 
-                               m = *((methodinfo **) (pv + MethodPointer));
+                               code = *((codeinfo **) (pv + CodeinfoPointer));
+
+                               /* For asm_vm_call_method the codeinfo pointer is
+                                  NULL. */
+
+                               m = (code == NULL) ? NULL : code->m;
 
                                /* if m == NULL, this is a asm_calljavafunction call */
 
                                if (m != NULL) {
 #if PRINTMETHODS
                                        printf("ra=%p sp=%p, ", ra, sp);
-                                       utf_display_classname(m->class->name);
-                                       printf(".");
-                                       utf_display(m->name);
-                                       utf_display(m->descriptor);
+                                       method_print(m);
                                        printf(": inline stub parent");
                                        fflush(stdout);
 #endif
@@ -857,34 +518,43 @@ static bool cacao_stacktrace_fillInStackTrace(void **target,
                                        if (!opt_intrp) {
 #endif
 
-                                       /* add it to the stacktrace */
+                                       /* add the method to the stacktrace */
 
-                                       stacktrace_fillInStackTrace_method(&buffer, m, pv,
-                                                                                                          (u1 *) ((ptrint) xpc));
+                                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
 
                                        /* get the current stack frame size */
 
                                        framesize = *((u4 *) (pv + FrameSize));
 
 #if PRINTMETHODS
-                                       printf(", framsize=%d\n", framesize);
+                                       printf(", framesize=%d\n", framesize);
                                        fflush(stdout);
 #endif
 
-                                       /* set stack pointer to stackframe of parent Java */
-                                       /* function of the current Java function */
+                                       /* Set stack pointer to stackframe of parent Java
+                                          function of the current Java function. */
 
-#if defined(__I386__) || defined (__X86_64__)
+#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
                                        sp += framesize + SIZEOF_VOID_P;
+#elif defined(__SPARC_64__)
+                                       sp = md_get_framepointer(sp);
 #else
                                        sp += framesize;
 #endif
 
-                                       /* get data segment and methodinfo pointer from parent */
-                                       /* method */
+                                       /* get data segment and methodinfo pointer from
+                                          parent method */
 
-                                       pv = (u1 *) (ptrint) codegen_findmethod(ra);
-                                       m = *((methodinfo **) (pv + MethodPointer));
+#if defined(ENABLE_JIT)
+                                       pv = md_codegen_get_pv_from_pc(ra);
+#endif
+
+                                       code = *((codeinfo **) (pv + CodeinfoPointer));
+
+                                       /* For asm_vm_call_method the codeinfo pointer is
+                                          NULL. */
+
+                                       m = (code == NULL) ? NULL : code->m;
 
 #if defined(ENABLE_INTRP)
                                        }
@@ -906,341 +576,426 @@ static bool cacao_stacktrace_fillInStackTrace(void **target,
                } else {
 #if PRINTMETHODS
                        printf("ra=%p sp=%p, ", ra, sp);
-                       utf_display_classname(m->class->name);
-                       printf(".");
-                       utf_display(m->name);
-                       utf_display(m->descriptor);
+                       method_print(m);
                        printf(": JIT");
                        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) */
+                       /* JIT method found, add it to the stacktrace (we subtract
+                          1 from the return address since it points the the
+                          instruction after call). */
 
-                       stacktrace_fillInStackTrace_method(&buffer, m, pv,
-                                                                                          (u1 *) ((ptrint) ra) - 1);
+                       stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
 
                        /* get the current stack frame size */
 
                        framesize = *((u4 *) (pv + FrameSize));
 
 #if PRINTMETHODS
-                       printf(", framsize=%d\n", framesize);
+                       printf(", framesize=%d\n", framesize);
                        fflush(stdout);
 #endif
 
                        /* get return address of current stack frame */
 
-                       ra = md_stacktrace_get_returnaddress(sp, framesize);
+#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
 
                        /* get data segment and methodinfo pointer from parent method */
 
-                       pv = (u1 *) (ptrint) codegen_findmethod(ra);
-                       m = *((methodinfo **) (pv + MethodPointer));
+#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
+                               }
+
+                       code = *((codeinfo **) (pv + CodeinfoPointer));
+
+                       /* For asm_vm_call_method the codeinfo pointer is NULL. */
+
+                       m = (code == NULL) ? NULL : code->m;
 
                        /* walk the stack */
 
 #if defined(ENABLE_INTRP)
                        if (opt_intrp)
-                               sp = *(u1 **)(sp - framesize);
+                               sp = *(u1 **) (sp - framesize);
                        else
 #endif
                                {
-#if defined(__I386__) || defined (__X86_64__)
+#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
                                        sp += framesize + SIZEOF_VOID_P;
+#elif defined(__SPARC_64__)
+                                       /* already has the new sp */
 #else
                                        sp += framesize;
 #endif
                                }
                }
        }
-                       
-       if (coll)
-               result = coll(target, &buffer);
 
-       if (buffer.needsFree)
-               free(buffer.start);
+       /* return the stacktracebuffer */
 
-       return result;
+       if (stb->used == 0)
+               return NULL;
+       else
+               return stb;
 }
 
 
-/* stackTraceCollector *********************************************************
+/* stacktrace_fillInStackTrace *************************************************
 
-   XXX
+   Generate a stacktrace from the current thread for
+   java.lang.VMThrowable.fillInStackTrace.
 
 *******************************************************************************/
-#ifdef ENABLE_JVMTI
-bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
-#else
-static bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
-#endif
+
+stacktracecontainer *stacktrace_fillInStackTrace(void)
 {
-       stackTraceBuffer *dest;
+       stacktracebuffer    *stb;
+       stacktracecontainer *gcstc;
+       s4                   gcstc_size;
+       s4                   dumpsize;
+       CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
 
-       dest = *target = heap_allocate(sizeof(stackTraceBuffer) + buffer->full * sizeof(stacktraceelement), true, 0);
+       /* mark start of dump memory area */
 
-       if (!dest)
-               return false;
+       dumpsize = dump_size();
 
-       memcpy(*target, buffer, sizeof(stackTraceBuffer));
-       memcpy(dest + 1, buffer->start, buffer->full * sizeof(stacktraceelement));
+       /* create a stacktrace from the current thread */
 
-       dest->needsFree = 0;
-       dest->size = dest->full;
-       dest->start = (stacktraceelement *) (dest + 1);
+       stb = stacktrace_create(STACKFRAMEINFO);
 
-       return true;
-}
+       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 */
 
-bool cacao_stacktrace_NormalTrace(void **target)
-{
-#ifdef ENABLE_JVMTI
-       return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector, NULL);
-#else
-       return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector);
-#endif
+       gcstc_size = sizeof(stacktracebuffer) +
+                    sizeof(stacktrace_entry) * stb->used;
+       gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
+
+       if (gcstc == 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);
+
+       /* release dump memory */
+
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+                                                                  stacktrace_overhead)
+       return gcstc;
+
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+                                                                  stacktrace_overhead)
+
+       return NULL;
 }
 
 
+/* stacktrace_getClassContext **************************************************
 
-static bool classContextCollector(void **target, stackTraceBuffer *buffer)
+   Creates a Class context array.
+
+   RETURN VALUE:
+      the array of java.lang.Class objects, or
+         NULL if an exception has been thrown
+
+*******************************************************************************/
+
+java_handle_objectarray_t *stacktrace_getClassContext(void)
 {
-       java_objectarray  *oa;
-       stacktraceelement *current;
-       stacktraceelement *start;
-       size_t size;
-       size_t targetSize;
-       s4 i;
-
-       size = buffer->full;
-       targetSize = 0;
-
-       for (i = 0; i < size; i++)
-               if (buffer->start[i].method != 0)
-                       targetSize++;
-
-       start = buffer->start;
-       start++;
-       targetSize--;
-
-       if (targetSize > 0) {
-               if (start->method &&
-                       (start->method->class == class_java_lang_SecurityManager)) {
-                       targetSize--;
-                       start++;
-               }
-       }
+       stacktracebuffer          *stb;
+       stacktrace_entry          *ste;
+       java_handle_objectarray_t *oa;
+       s4                         oalength;
+       s4                         i;
+       s4                         dumpsize;
+       CYCLES_STATS_DECLARE_AND_START
 
-       oa = builtin_anewarray(targetSize, class_java_lang_Class);
+       /* mark start of dump memory area */
 
+       dumpsize = dump_size();
+
+       /* create a stacktrace for the current thread */
+
+       stb = stacktrace_create(STACKFRAMEINFO);
+
+       if (stb == NULL)
+               goto return_NULL;
+
+       /* calculate the size of the Class array */
+
+       for (i = 0, oalength = 0; i < stb->used; i++)
+               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--;
+
+       /* allocate the Class array */
+
+       oa = builtin_anewarray(oalength, class_java_lang_Class);
        if (!oa)
-               return false;
+               goto return_NULL;
 
-       for(i = 0, current = start; i < targetSize; i++, current++) {
-               if (!current->method) {
+       /* fill the Class array from the stacktracebuffer */
+
+       for(i = 0; i < oalength; i++, ste++) {
+               if (ste->method == NULL) {
                        i--;
                        continue;
                }
 
-               use_class_as_object(current->method->class);
-
-               oa->data[i] = (java_objectheader *) current->method->class;
+               oa->data[i] = (java_object_t *) ste->method->class;
        }
 
-       *target = oa;
+       /* release dump memory */
 
-       return true;
-}
+       dump_release(dumpsize);
 
+       CYCLES_STATS_END(stacktrace_getClassContext)
 
+       return oa;
 
-java_objectarray *cacao_createClassContextArray(void)
-{
-       java_objectarray *array = NULL;
+return_NULL:
+       dump_release(dumpsize);
 
-#ifdef ENABLE_JVMTI
-       if (!cacao_stacktrace_fillInStackTrace((void **) &array,
-                                                                                  &classContextCollector, NULL))
-#else
-       if (!cacao_stacktrace_fillInStackTrace((void **) &array,
-                                                                                  &classContextCollector))
-#endif
-               return NULL;
+       CYCLES_STATS_END(stacktrace_getClassContext)
 
-       return array;
+       return NULL;
 }
 
 
-/* stacktrace_classLoaderCollector *********************************************
+/* stacktrace_getCurrentClass **************************************************
 
-   XXX
+   Find the current class by walking the stack trace.
+
+   Quote from the JNI documentation:
+        
+   In the Java 2 Platform, FindClass locates the class loader
+   associated with the current native method.  If the native code
+   belongs to a system class, no class loader will be
+   involved. Otherwise, the proper class loader will be invoked to
+   load and link the named class. When FindClass is called through the
+   Invocation Interface, there is no current native method or its
+   associated class loader. In that case, the result of
+   ClassLoader.getBaseClassLoader is used."
 
 *******************************************************************************/
 
-static bool stacktrace_classLoaderCollector(void **target,
-                                                                                       stackTraceBuffer *buffer)
+#if defined(ENABLE_JAVASE)
+classinfo *stacktrace_getCurrentClass(void)
 {
-       stacktraceelement *current;
-       stacktraceelement *start;
+       stacktracebuffer  *stb;
+       stacktrace_entry  *ste;
        methodinfo        *m;
-       ptrint             size;
        s4                 i;
+       s4                 dumpsize;
+       CYCLES_STATS_DECLARE_AND_START
+
+       /* mark start of dump memory area */
+
+       dumpsize = dump_size();
 
-       size = buffer->full;
-       start = &(buffer->start[0]);
+       /* create a stacktrace for the current thread */
 
-       for(i = 0, current = start; i < size; i++, current++) {
-               m = current->method;
+       stb = stacktrace_create(STACKFRAMEINFO);
 
-               if (!m)
+       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 */
+
+       for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
+               m = ste->method;
+
+               if (m == NULL)
                        continue;
 
-               if (m->class == class_java_security_PrivilegedAction) {
-                       *target = NULL;
-                       return true;
-               }
+               if (m->class == class_java_security_PrivilegedAction)
+                       goto return_NULL;
+
+               if (m->class != NULL) {
+                       dump_release(dumpsize);
 
-               if (m->class->classloader) {
-                       *target = (java_lang_ClassLoader *) m->class->classloader;
-                       return true;
+                       CYCLES_STATS_END(stacktrace_getCurrentClass)
+
+                       return m->class;
                }
        }
 
-       *target = NULL;
+       /* no Java method found on the stack */
 
-       return true;
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getCurrentClass)
+
+       return NULL;
 }
+#endif /* ENABLE_JAVASE */
+
 
+/* stacktrace_getStack *********************************************************
 
-/* cacao_currentClassLoader ****************************************************
+   Create a 2-dimensional array for java.security.VMAccessControler.
 
-   XXX
+   RETURN VALUE:
+      the arrary, or
+         NULL if an exception has been thrown
 
 *******************************************************************************/
 
-java_objectheader *cacao_currentClassLoader(void)
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *stacktrace_getStack(void)
 {
-       java_objectheader *header = NULL;
+       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 */
 
-#ifdef ENABLE_JVMTI
-       if (!cacao_stacktrace_fillInStackTrace((void**)&header,
-                                                                                  &stacktrace_classLoaderCollector,
-                                                                                  NULL))
-#else
-       if (!cacao_stacktrace_fillInStackTrace((void**)&header,
-                                                                                  &stacktrace_classLoaderCollector))
-#endif
-               return NULL;
+       dumpsize = dump_size();
 
-       return header;
-}
+       /* create a stacktrace for the current thread */
 
+       stb = stacktrace_create(STACKFRAMEINFO);
 
-static bool getStackCollector(void **target, stackTraceBuffer *buffer)
-{
-       java_objectarray  *oa;
-       java_objectarray  *classes;
-       java_objectarray  *methodnames;
-       java_lang_String  *str;
-       classinfo         *c;
-       stacktraceelement *current;
-       s4                 i, size;
+       if (stb == NULL)
+               goto return_NULL;
+
+       /* get the first stacktrace entry */
 
-/*     *result = (java_objectarray **) target; */
+       ste = &(stb->entries[0]);
 
-       size = buffer->full;
+       /* allocate all required arrays */
 
        oa = builtin_anewarray(2, arrayclass_java_lang_Object);
 
-       if (!oa)
-               return false;
+       if (oa == NULL)
+               goto return_NULL;
+
+       classes = builtin_anewarray(stb->used, class_java_lang_Class);
+
+       if (classes == NULL)
+               goto return_NULL;
 
-       classes = builtin_anewarray(size, class_java_lang_Class);
+       methodnames = builtin_anewarray(stb->used, class_java_lang_String);
 
-       if (!classes)
-               return false;
+       if (methodnames == NULL)
+               goto return_NULL;
 
-       methodnames = builtin_anewarray(size, class_java_lang_String);
+       /* set up the 2-dimensional array */
 
-       if (!methodnames)
-               return false;
+       oa->data[0] = (java_object_t *) classes;
+       oa->data[1] = (java_object_t *) methodnames;
 
-       oa->data[0] = (java_objectheader *) classes;
-       oa->data[1] = (java_objectheader *) methodnames;
+       /* iterate over all stacktrace entries */
 
-       for (i = 0, current = &(buffer->start[0]); i < size; i++, current++) {
-               c = current->method->class;
+       for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
+               c = ste->method->class;
 
-               use_class_as_object(c);
+               classes->data[i] = (java_object_t *) c;
 
-               classes->data[i] = (java_objectheader *) c;
-               str = javastring_new(current->method->name);
+               string = javastring_new(ste->method->name);
 
-               if (!str)
-                       return false;
+               if (string == NULL)
+                       goto return_NULL;
 
-               methodnames->data[i] = (java_objectheader *) str;
+               methodnames->data[i] = string;
        }
 
-       *target = oa;
+       /* return the 2-dimensional array */
 
-       return true;
-}
+       dump_release(dumpsize);
 
+       CYCLES_STATS_END(stacktrace_getStack)
 
-java_objectarray *cacao_getStackForVMAccessController(void)
-{
-       java_objectarray *result = NULL;
+       return oa;
 
-#ifdef ENABLE_JVMTI
-       if (!cacao_stacktrace_fillInStackTrace((void **) &result,
-                                                                                  &getStackCollector,NULL))
-#else
-       if (!cacao_stacktrace_fillInStackTrace((void **) &result,
-                                                                                  &getStackCollector))
-#endif
-               return NULL;
+return_NULL:
+       dump_release(dumpsize);
 
-       return result;
+       CYCLES_STATS_END(stacktrace_getStack)
+
+       return NULL;
 }
+#endif /* ENABLE_JAVASE */
 
 
 /* stacktrace_print_trace_from_buffer ******************************************
 
-   Print the stacktrace of a given stackTraceBuffer with CACAO intern
+   Print the stacktrace of a given stacktracebuffer with CACAO intern
    methods (no Java help). This method is used by
    stacktrace_dump_trace and builtin_trace_exception.
 
 *******************************************************************************/
 
-static void stacktrace_print_trace_from_buffer(stackTraceBuffer *stb)
+void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
 {
-       stacktraceelement *ste;
-       methodinfo        *m;
-       s4                 i;
+       stacktrace_entry *ste;
+       methodinfo       *m;
+       s4                i;
 
-       ste = stb->start;
+       ste = &(stb->entries[0]);
 
-       for (i = 0; i < stb->size; i++, ste++) {
+       for (i = 0; i < stb->used; i++, ste++) {
                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);
                }
        }
@@ -1251,49 +1006,6 @@ static 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(void)
-{
-       stackTraceBuffer      *buffer;
-
-#if 0
-       /* get thread stackframeinfo */
-
-       info = &THREADINFO->_stackframeinfo;
-
-       /* fill stackframeinfo structure */
-
-       tmp.oldThreadspecificHeadValue = *info;
-       tmp.addressOfThreadspecificHead = info;
-       tmp.method = NULL;
-       tmp.sp = NULL;
-       tmp.ra = _mc->gregs[REG_RIP];
-
-       *info = &tmp;
-#endif
-
-       /* generate stacktrace */
-
-       cacao_stacktrace_NormalTrace((void **) &buffer);
-
-       /* print stacktrace */
-
-       if (buffer) {
-               stacktrace_print_trace_from_buffer(buffer);
-
-       } else {
-               puts("\t<<No stacktrace available>>");
-               fflush(stdout);
-       }
-}
-
-
 /* stacktrace_print_trace ******************************************************
 
    Print the stacktrace of a given exception. More or less a wrapper
@@ -1301,23 +1013,49 @@ void stacktrace_dump_trace(void)
 
 *******************************************************************************/
 
-void stacktrace_print_trace(java_objectheader *xptr)
+void stacktrace_print_trace(java_handle_t *xptr)
 {
        java_lang_Throwable   *t;
+#if defined(WITH_CLASSPATH_GNU)
        java_lang_VMThrowable *vmt;
-       stackTraceBuffer      *stb;
+#endif
+       stacktracecontainer   *stc;
+       stacktracebuffer      *stb;
 
        t = (java_lang_Throwable *) xptr;
 
+       if (t == NULL)
+               return;
+
        /* now print the stacktrace */
 
-       vmt = t->vmState;
-       stb = (stackTraceBuffer *) vmt->vmData;
+#if defined(WITH_CLASSPATH_GNU)
+       LLNI_field_get_ref(t, vmState, vmt);
+       stc = (stacktracecontainer *) LLNI_field_direct(vmt, vmData);
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+       stc = (stacktracecontainer *) t->backtrace;
+#else
+# error unknown classpath configuration
+#endif
+
+       stb = &(stc->stb);
 
        stacktrace_print_trace_from_buffer(stb);
 }
 
 
+#if defined(ENABLE_CYCLES_STATS)
+void stacktrace_print_cycles_stats(FILE *file)
+{
+       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
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -1329,4 +1067,5 @@ void stacktrace_print_trace(java_objectheader *xptr)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */