* Removed all Id tags.
[cacao.git] / src / vm / jit / stacktrace.c
index 630458f5e439f1bd4dcb950c1e7e56c06cea6387..98e96d149af0121bbf9933d24e52524131b7824b 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
-
-   $Id: stacktrace.c 4430 2006-02-04 19:04:31Z twisti $
-
 */
 
 
 
 #include "vm/types.h"
 
-#include "mm/boehm.h"
-#include "native/native.h"
+#include "mm/gc-common.h"
+#include "mm/memory.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/vm.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/methodheader.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;
-       u1     *pc;
-};
-
-
-#if 0
-typedef struct lineNumberTableEntryInlineBegin {
-       /* this should have the same layout and size as the lineNumberTableEntry */
-       ptrint      lineNrOuter;
-       methodinfo *method;
-} lineNumberTableEntryInlineBegin;
-#endif
+#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 ********************************************
 
@@ -103,29 +95,34 @@ void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
 {
        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) {
 #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);
+                               pv = md_codegen_get_pv_from_pc(ra);
 #endif
                        }
        }
 
-       /* get methodinfo pointer from data segment */
+       /* get codeinfo pointer from data segment */
+
+       code = *((codeinfo **) (pv + CodeinfoPointer));
+
+       /* 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 */
 
@@ -146,46 +143,6 @@ void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
 #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);
-
-       }
-#endif
-
-       /* fill new stackframe info structure */
-
-       sfi->prev   = *psfi;
-       sfi->method = NULL;
-       sfi->pv     = pv;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-       sfi->xpc    = xpc;
-
-       /* store new stackframe info pointer */
-
-       *psfi = sfi;
-}
-
-
 /* stacktrace_create_extern_stackframeinfo *************************************
 
    Creates an stackframe info structure for an extern exception
@@ -197,7 +154,7 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
                                                                                         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)
@@ -206,7 +163,7 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 
        /* 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). */
@@ -214,12 +171,16 @@ 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
                        }
        }
@@ -230,9 +191,12 @@ void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 
        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));
 
@@ -282,14 +246,19 @@ void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 {
        stackframeinfo **psfi;
        methodinfo      *m;
+       codeinfo        *code;
+
+       /* 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;
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        /* fill new stackframe info structure */
 
@@ -308,7 +277,7 @@ void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 
 /* stacktrace_remove_stackframeinfo ********************************************
 
-   XXX
+   Remove the topmost stackframeinfo in the current thread.
 
 *******************************************************************************/
 
@@ -318,7 +287,7 @@ void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
 
        /* get current stackframe info pointer */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        /* restore the old pointer */
 
@@ -326,249 +295,6 @@ void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
 }
 
 
-/* stacktrace_inline_arithmeticexception ***************************************
-
-   Creates an ArithemticException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
-                                                                                                                u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = 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,
-                                                                                                                                       u1 *ra,
-                                                                                                                                       u1 *xpc,
-                                                                                                                                       s4 index)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_arrayindexoutofboundsexception(index);
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_arraystoreexception ***************************************
-
-   Creates an ArrayStoreException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                                u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_arraystoreexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_classcastexception ****************************************
-
-   Creates an ClassCastException for inline stub.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                               u1 *xpc)
-{
-       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,
-                                                                                                                 u1 *ra, u1 *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,
-                                                                                                                  u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_arithmeticexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_hardware_nullpointerexception ************************************
-
-   Creates an NullPointerException for the SIGSEGV signal handler.
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
-                                                                                                                       u1 *ra, u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* create exception */
-
-       o = new_nullpointerexception();
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
-/* stacktrace_inline_fillInStackTrace ******************************************
-
-   Fills in the correct stacktrace into an existing exception object
-   (this one is for inline exception stubs).
-
-*******************************************************************************/
-
-java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                         u1 *xpc)
-{
-       stackframeinfo     sfi;
-       java_objectheader *o;
-       methodinfo        *m;
-
-       /* create stackframeinfo */
-
-       stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       /* get exception */
-
-       o = *exceptionptr;
-
-       /* 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 */
-
-       ASM_CALLJAVAFUNCTION(m, o, NULL, NULL, NULL);
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       return o;
-}
-
-
 /* stacktrace_add_entry ********************************************************
 
    Adds a new entry to the stacktrace buffer.
@@ -605,83 +331,41 @@ static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
 }
 
 
-/* stacktrace_fillInStackTrace_method ******************************************
+/* stacktrace_add_method *******************************************************
+
+   Add stacktrace entries[1] for the given method to the stacktrace buffer.
+
+   IN:
+       stb.........stacktracebuffer to fill
+          m...........method for which entries should be created
+          pv..........pv of method
+          pc..........position of program counter within the method's code
+
+   OUT:
+       true, if stacktrace entries were successfully created, false otherwise.
 
-   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_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
                                                                  u1 *pc)
 {
-       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     */
+       s4        linenumber;
 
-       /* get size of line number table */
+       /* find the realization of the method the pc is in */
 
-       lntsize  = *((ptrint *) (pv + LineNumberTableSize));
-       lntstart = *((u1 **)    (pv + LineNumberTableStart));
+       code = *((codeinfo **) (pv + CodeinfoPointer));
 
-       /* Subtract the size of the line number entry of the structure,
-          since the line number table start points to the pc. */
+       /* search the line number table */
 
-       lntentry = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
+       linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
 
-       /* Find the line number for the specified PC (going backwards
-          in the linenumber table). The linenumber table size is zero
-          in native stubs. */
+       /* now add a new entry to the staktrace */
 
-       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 */
-
-                       case -1: /* begin of inlined method */
-                               lntinline = (lineNumberTableEntryInlineBegin *) (--lntentry);
-                               lntentry++;
-                               lntsize--; lntsize--;
-                               if (stacktrace_fillInStackTrace_methodRecursive(buffer,
-                                                                                                                               ilStart->method,
-                                                                                                                               ent,
-                                                                                                                               &ent,
-                                                                                                                               &ahead,
-                                                                                                                               pc)) {
-                                       stacktrace_add_entry(buffer, m, ilStart->lineNrOuter);
-
-                                       return true;
-                               }
-                               break;
-
-                       case -2: /* end of inlined method */
-                               *entry = ent;
-                               *entriesAhead = ahead;
-                               return false;
-                               break;
-#endif
-
-                       default:
-                               stacktrace_add_entry(stb, m, lntentry->line);
-                               return true;
-                       }
-               }
-       }
-
-       /* check if we are before the actual JIT code */
-
-       if ((ptrint) pc < (ptrint) m->entrypoint) {
-               dolog("Current PC before start of code: %p < %p", pc, m->entrypoint);
-               assert(0);
-       }
-
-       /* If we get here, just add the entry with line number 0. */
-
-       stacktrace_add_entry(stb, m, 0);
+       stacktrace_add_entry(stb, m, linenumber);
 
        return true;
 }
@@ -690,28 +374,31 @@ static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
 /* 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 *sfi)
 {
        stacktracebuffer *stb;
-       stacktracebuffer *gcstb;
-       s4                dumpsize;
-       stackframeinfo   *sfi;
        methodinfo       *m;
+       codeinfo         *code;
        u1               *pv;
        u1               *sp;
        u4                framesize;
        u1               *ra;
        u1               *xpc;
 
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
        /* prevent compiler warnings */
 
        pv = NULL;
@@ -726,12 +413,6 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
        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). */
-
-       sfi = thread->info._stackframeinfo;
-
 #define PRINTMETHODS 0
 
 #if PRINTMETHODS
@@ -744,7 +425,7 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
 
        m = NULL;
 
-       while (m || sfi) {
+       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. */
@@ -774,18 +455,23 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
 
 #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);
+                                               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
@@ -811,7 +497,12 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
 
                                /* 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 */
 
@@ -840,23 +531,30 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
                                        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 */
 
 #if defined(ENABLE_JIT)
-                                       pv = md_codegen_findmethod(ra);
+                                       pv = md_codegen_get_pv_from_pc(ra);
 #endif
 
-                                       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 defined(ENABLE_INTRP)
                                        }
@@ -915,16 +613,25 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
 
 #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__)
+                                       sp = md_get_framepointer(sp);
+                                       pv = md_get_pv_from_stackframe(sp);
+# else
+                                       pv = md_codegen_get_pv_from_pc(ra);
+# endif
 #endif
                                }
 
-                       m = *((methodinfo **) (pv + MethodPointer));
+                       code = *((codeinfo **) (pv + CodeinfoPointer));
+
+                       /* For asm_vm_call_method the codeinfo pointer is NULL. */
+
+                       m = (code == NULL) ? NULL : code->m;
 
                        /* walk the stack */
 
@@ -934,8 +641,10 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
                        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
@@ -943,48 +652,73 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
                }
        }
 
-       /* allocate memory from the GC heap and copy the stacktrace buffer */
+       /* return the stacktracebuffer */
 
-       gcstb = GCNEW(stacktracebuffer);
+       if (stb->used == 0)
+               return NULL;
+       else
+               return stb;
+}
 
 
-       gcstb->capacity = stb->capacity;
-       gcstb->used     = stb->used;
-       gcstb->entries  = GCMNEW(stacktrace_entry, stb->used);
+/* stacktrace_fillInStackTrace *************************************************
 
-       MCOPY(gcstb->entries, stb->entries, stacktrace_entry, stb->used);
+   Generate a stacktrace from the current thread for
+   java.lang.VMThrowable.fillInStackTrace.
 
-       /* just to be sure */
+*******************************************************************************/
 
-       stb = NULL;
-       assert(gcstb != NULL);
+stacktracecontainer *stacktrace_fillInStackTrace(void)
+{
+       stacktracebuffer    *stb;
+       stacktracecontainer *gcstc;
+       s4                   gcstc_size;
+       s4                   dumpsize;
+       CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
 
-       /* release dump memory */
+       /* mark start of dump memory area */
 
-       dump_release(dumpsize);
+       dumpsize = dump_size();
 
-       /* return the stacktracebuffer */
+       /* create a stacktrace from the current thread */
 
-       return gcstb;
-}
+       stb = stacktrace_create(STACKFRAMEINFO);
 
+       if (stb == NULL)
+               goto return_NULL;
 
-/* stacktrace_fillInStackTrace *************************************************
+       /* allocate memory from the GC heap and copy the stacktrace buffer */
+       /* ATTENTION: use stacktracecontainer for this and make it look like
+       an array */
 
-   Generate a stacktrace from the current thread for
-   java.lang.VMThrowable.fillInStackTrace.
+       gcstc_size = sizeof(stacktracebuffer) +
+                    sizeof(stacktrace_entry) * stb->used;
+       gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
 
-*******************************************************************************/
+       if (gcstc == NULL)
+               goto return_NULL;
 
-stacktracebuffer *stacktrace_fillInStackTrace(void)
-{
-       stacktracebuffer *stb;
+       gcstc->stb.capacity = stb->capacity;
+       gcstc->stb.used     = stb->used;
+       gcstc->stb.entries  = gcstc->data;
 
-       /* create a stacktrace from the current thread */
+       MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
+
+       /* release dump memory */
+
+       dump_release(dumpsize);
 
-       stb = stacktrace_create(THREADOBJECT);
+       CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+                                                                  stacktrace_overhead)
+       return gcstc;
 
-       return stb;
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+                                                                  stacktrace_overhead)
+
+       return NULL;
 }
 
 
@@ -992,19 +726,32 @@ stacktracebuffer *stacktrace_fillInStackTrace(void)
 
    Creates a Class context array.
 
+   RETURN VALUE:
+      the array of java.lang.Class objects, or
+         NULL if an exception has been thrown
+
 *******************************************************************************/
 
-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 */
 
@@ -1012,26 +759,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 */
 
@@ -1041,79 +780,131 @@ java_objectarray *stacktrace_getClassContext(void)
                        continue;
                }
 
-               oa->data[i] = (java_objectheader *) ste->method->class;
+               oa->data[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;
 }
 
 
-/* stacktrace_getCurrentClassLoader ********************************************
+/* stacktrace_getCurrentClass **************************************************
+
+   Find the current class by walking the stack trace.
 
-   XXX
+   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."
 
 *******************************************************************************/
 
-java_objectheader *stacktrace_getCurrentClassLoader(void)
+#if defined(ENABLE_JAVASE)
+classinfo *stacktrace_getCurrentClass(void)
 {
        stacktracebuffer  *stb;
        stacktrace_entry  *ste;
        methodinfo        *m;
-       java_objectheader *cl;
        s4                 i;
+       s4                 dumpsize;
+       CYCLES_STATS_DECLARE_AND_START
+
+       /* mark start of dump memory area */
 
-       cl = NULL;
+       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
-          classloader */
+          class */
 
        for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
                m = ste->method;
 
-               if (!m)
+               if (m == NULL)
                        continue;
 
-               if (m->class == class_java_security_PrivilegedAction) {
-                       cl = NULL;
-                       break;
-               }
+               if (m->class == class_java_security_PrivilegedAction)
+                       goto return_NULL;
+
+               if (m->class != NULL) {
+                       dump_release(dumpsize);
+
+                       CYCLES_STATS_END(stacktrace_getCurrentClass)
 
-               if (m->class->classloader) {
-                       cl = m->class->classloader;
-                       break;
+                       return m->class;
                }
        }
 
-       /* return the classloader */
+       /* no Java method found on the stack */
+
+return_NULL:
+       dump_release(dumpsize);
+
+       CYCLES_STATS_END(stacktrace_getCurrentClass)
 
-       return cl;
+       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 */
 
@@ -1123,42 +914,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;
+       oa->data[0] = (java_object_t *) classes;
+       oa->data[1] = (java_object_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);
+               classes->data[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;
+
+               methodnames->data[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 ******************************************
@@ -1169,7 +973,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;
@@ -1181,17 +985,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);
                }
        }
@@ -1202,56 +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)
-{
-       stackframeinfo   *psfi;
-       stacktracebuffer *stb;
-
-#if 0
-       /* get methodinfo pointer from data segment */
-
-       m = *((methodinfo **) (pv + MethodPointer));
-
-       /* get current stackframe info pointer */
-
-       psfi = STACKFRAMEINFO;
-
-       /* fill new stackframe info structure */
-
-       sfi->prev   = *psfi;
-       sfi->method = NULL;
-       sfi->pv     = NULL;
-       sfi->sp     = sp;
-       sfi->ra     = ra;
-
-       /* store new stackframe info pointer */
-
-       *psfi = sfi;
-#endif
-
-       /* create a stacktrace for the current thread */
-
-       stb = stacktrace_create(THREADOBJECT);
-
-       /* print stacktrace */
-
-       if (stb) {
-               stacktrace_print_trace_from_buffer(stb);
-
-       } else {
-               puts("\t<<No stacktrace available>>");
-               fflush(stdout);
-       }
-}
-
-
 /* stacktrace_print_trace ******************************************************
 
    Print the stacktrace of a given exception. More or less a wrapper
@@ -1259,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;
+#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