almost all required function implemented - first integration with jdwp - nothing...
[cacao.git] / src / vm / jit / stacktrace.c
index 4bbc9b25944c545f8fb0055e28d6a460b389e05b..7efb26565df152dd5fa551943db301587f466d86 100644 (file)
@@ -1,4 +1,4 @@
-/* vm/jit/stacktrace.c
+/* src/vm/jit/stacktrace.c - machine independet stacktrace system
 
    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
 
    Authors: Joseph Wenninger
 
-   $Id: stacktrace.c 1929 2005-02-10 10:52:26Z twisti $
+   Changes: Christian Thalinger
+
+   $Id: stacktrace.c 3570 2005-11-04 16:58:36Z motse $
 
 */
 
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "asmoffsets.h"
+#include "config.h"
+
 #include "mm/boehm.h"
 #include "native/native.h"
+
 #include "vm/global.h"                   /* required here for native includes */
 #include "native/include/java_lang_ClassLoader.h"
+
 #include "toolbox/logging.h"
 #include "vm/builtin.h"
 #include "vm/class.h"
+#include "vm/exceptions.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/stringlocal.h"
 #include "vm/tables.h"
+#include "vm/jit/asmpart.h"
 #include "vm/jit/codegen.inc.h"
+#include "vm/jit/methodheader.h"
 
 
-#undef JWDEBUG
-/*JoWenn: simplify collectors (trace doesn't contain internal methods)*/
+/* lineNumberTableEntry *******************************************************/
 
-/* the line number is only u2, but to avoid alignment problems it is made the same size as a native
-       pointer. In the structures where this is used, values of -1 or -2 have a special meainging, so
-       if java bytecode is ever extended to support more than 65535 lines/file, this could will have to
-       be changed.*/
-
-#ifdef _ALPHA_
-       #define LineNumber u8
-#else
-       #define LineNumber u4
-#endif
+/* Keep the type of line the same as the pointer type, otherwise we run into  */
+/* alignment troubles (like on MIPS64).                                       */
 
 typedef struct lineNumberTableEntry {
-/* The special value of -1 means that a inlined function starts, a value of -2 means that an inlined function ends*/
-       LineNumber lineNr;
-       void *pc;
+       ptrint  line;
+       u1     *pc;
 } lineNumberTableEntry;
 
+
 typedef struct lineNumberTableEntryInlineBegin {
-/*this should have the same layout and size as the lineNumberTableEntry*/
-       LineNumber lineNrOuter;
+       /* this should have the same layout and size as the lineNumberTableEntry */
+       ptrint      lineNrOuter;
        methodinfo *method;
 } lineNumberTableEntryInlineBegin;
 
-
-typedef void(*CacaoStackTraceCollector)(void **,stackTraceBuffer*);
+#ifndef ENABLE_JVMTI
+typedef bool(*CacaoStackTraceCollector)(void **, stackTraceBuffer*);
+#endif
 
 #define BLOCK_INITIALSIZE 40
 #define BLOCK_SIZEINCREMENT 40
 
-static void addEntry(stackTraceBuffer* buffer,methodinfo*method ,LineNumber line) {
-       if (buffer->size>buffer->full) {
-               stacktraceelement *tmp=&(buffer->start[buffer->full]);
-               tmp->method=method;
-               tmp->linenumber=line;
-               buffer->full = buffer->full + 1;
-#ifdef JWDEBUG
-               log_text("addEntry (stacktrace):");
-               if (method) utf_display(method->name); else printf("Native");
-               if (method) {printf("\n");utf_display(method->class->name);}
-               printf("\nLine:%ld\n",line);
+
+/* global variables ***********************************************************/
+
+#if !defined(USE_THREADS)
+stackframeinfo *_no_threads_stackframeinfo = NULL;
 #endif
+
+
+/* stacktrace_create_stackframeinfo ********************************************
+
+   Creates an stackframe info structure for inline code in the
+   interpreter.
+
+*******************************************************************************/
+
+#if defined(ENABLE_INTRP)
+void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv,
+                                                                         u1 *sp, functionptr ra)
+{
+       stackframeinfo **psfi;
+       methodinfo      *m;
+
+       /* get current stackframe info pointer */
+
+       psfi = STACKFRAMEINFO;
+
+       /* if we don't have pv handy */
+
+       if (pv == NULL)
+               pv = (u1 *) (ptrint) codegen_findmethod(ra);
+
+       /* get methodinfo pointer from data segment */
+
+       m = *((methodinfo **) (pv + MethodPointer));
+
+       /* fill new stackframe info structure */
+
+       sfi->prev = *psfi;
+       sfi->method = m;
+       sfi->pv = pv;
+       sfi->sp = sp;
+       sfi->ra = ra;
+
+       /* xpc is the same as ra, but is required in fillInStackTrace */
+
+       sfi->xpc = ra;
+
+       /* store new stackframe info pointer */
+
+       *psfi = sfi;
+}
+#endif /* defined(ENABLE_INTRP) */
+
+/* stacktrace_create_inline_stackframeinfo *************************************
+
+   Creates an stackframe info structure for an inline exception stub.
+
+*******************************************************************************/
+
+void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
+                                                                                        u1 *sp, 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 *************************************
+
+   Creates an stackframe info structure for an extern exception
+   (hardware or assembler).
+
+*******************************************************************************/
+
+void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
+                                                                                        u1 *sp, functionptr ra,
+                                                                                        functionptr xpc)
+{
+       stackframeinfo **psfi;
+#if !defined(__I386__) && !defined(__X86_64__)
+       bool             isleafmethod;
+#endif
+       s4               framesize;
+
+       /* get current stackframe info pointer */
+
+       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 defined(ENABLE_INTRP)
+       /* When using the interpreter, we pass RA to the function. */
+
+       if (!opt_intrp) {
+#endif
+# if defined(__I386__) || defined(__X86_64__)
+               /* On i386 and x86_64 we always have to get the return address
+                  from the stack. */
+
+               framesize = *((u4 *) (pv + FrameSize));
+
+               ra = md_stacktrace_get_returnaddress(sp, framesize);
+# else
+               /* If the method is a non-leaf function, we need to get the return
+                  address from the stack. For leaf functions the return address
+                  is set correctly. This makes the assembler and the signal
+                  handler code simpler. */
+
+               isleafmethod = *((s4 *) (pv + IsLeaf));
+
+               if (!isleafmethod) {
+                       framesize = *((u4 *) (pv + FrameSize));
+
+                       ra = md_stacktrace_get_returnaddress(sp, framesize);
+               }
+# endif
+#if defined(ENABLE_INTRP)
+       }
+#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_native_stackframeinfo *************************************
+
+   Creates a stackframe info structure for a native stub.
+
+*******************************************************************************/
+
+void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
+                                                                                        u1 *sp, functionptr ra)
+{
+       stackframeinfo **psfi;
+       methodinfo      *m;
+
+       /* 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 = m;
+       sfi->pv = NULL;
+       sfi->sp = sp;
+       sfi->ra = ra;
+       sfi->xpc = NULL;
+
+       /* store new stackframe info pointer */
+
+       *psfi = sfi;
+}
+
+
+/* stacktrace_remove_stackframeinfo ********************************************
+
+   XXX
+
+*******************************************************************************/
+
+void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
+{
+       stackframeinfo **psfi;
+
+       /* get current stackframe info pointer */
+
+       psfi = STACKFRAMEINFO;
+
+       /* restore the old pointer */
+
+       *psfi = sfi->prev;
+}
+
+
+/* stacktrace_inline_arithmeticexception ***************************************
+
+   Creates an ArithemticException for inline stub.
+
+*******************************************************************************/
+
+java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
+                                                                                                                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 ************************************
+
+   Creates an NullPointerException for the SIGSEGV signal handler.
+
+*******************************************************************************/
+
+java_objectheader *stacktrace_hardware_nullpointerexception(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_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,
+                                                                                                         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);
+
+       /* call function */
+
+       asm_calljavafunction(m, o, NULL, NULL, NULL);
+
+       /* remove stackframeinfo */
+
+       stacktrace_remove_stackframeinfo(&sfi);
+
+       return o;
+}
+
+
+/* addEntry ********************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+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=(stacktraceelement*)
-                       malloc((buffer->size+BLOCK_SIZEINCREMENT)*sizeof(stacktraceelement));
-               if (newBuffer==0) panic("OOM during stacktrace creation");
-               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);
+               stacktraceelement *newBuffer;
+
+               newBuffer =
+                       (stacktraceelement *) malloc((buffer->size + BLOCK_SIZEINCREMENT) *
+                                                                                sizeof(stacktraceelement));
+
+               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);
        }
 }
 
-static int fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,methodinfo 
-               *method,lineNumberTableEntry *startEntry, lineNumberTableEntry **entry, size_t *entriesAhead,void *adress) {
-
-       size_t ahead=*entriesAhead;
-       lineNumberTableEntry *ent=*entry;
-       lineNumberTableEntryInlineBegin *ilStart;
-
-       for (;ahead>0;ahead--,ent++) {
-               if (adress>=ent->pc) {
-                       switch (ent->lineNr) {
-                               case -1: /*begin of inlined method */
-                                       ilStart=(lineNumberTableEntryInlineBegin*)(++ent);
-                                       ent ++;
-                                       ahead--; ahead--;
-                                       if (fillInStackTrace_methodRecursive(buffer,ilStart->method,ent,&ent,&ahead,adress)) {
-                                               addEntry(buffer,method,ilStart->lineNrOuter);
-                                               return 1;
-                                       }
-                                       break;
-                               case -2: /*end of inlined method*/
-                                       *entry=ent;
-                                       *entriesAhead=ahead;
-                                       return 0;
-                                       break;
-                               default:
-                                       if (adress==ent->pc) {
-                                               addEntry(buffer,method,ent->lineNr);
-                                               return 1;
-                                       }
-                                       break;
+
+/* stacktrace_fillInStackTrace_methodRecursive *********************************
+
+   XXX
+
+*******************************************************************************/
+
+static bool stacktrace_fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,
+                                                                                                               methodinfo *m,
+                                                                                                               lineNumberTableEntry *lntentry,
+                                                                                                               s4 lntsize,
+                                                                                                               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 */
+
+                       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);
+
+                                       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;
                        }
-               } else {
-                       if (adress>startEntry->pc) {
-                               ent--;
-                               addEntry(buffer,method,ent->lineNr);
-                               return 1;       
-                       } else panic("trace point before method");
                }
        }
-       ent--;
-       addEntry(buffer,method,ent->lineNr);
-       return 1;
-       
+
+       /* 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);
+       }
+
+       /* otherwise just add line 0 */
+
+       addEntry(buffer, m, 0);
+
+       return true;
 }
 
-static void fillInStackTrace_method(stackTraceBuffer *buffer,methodinfo *method,char *dataSeg, void* adress) {
-       size_t lineNumberTableSize=(*((size_t*)(dataSeg+LineNumberTableSize)));
 
+/* 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);
+
+       if (lntsize == 0) {
+               /* this happens when an exception is thrown in the native stub */
+
+               addEntry(buffer, method, 0);
 
-       if ( lineNumberTableSize == 0) {
-               /*right now this happens only on 
-               i386,if the native stub causes an exception in a <clinit> invocation (jowenn)*/
-               addEntry(buffer,method,0);
-               return;
        } else {
-               lineNumberTableEntry *ent; /*=(lineNumberTableEntry*) ((*((char**)(dataSeg+LineNumberTableStart))) - (sizeof(lineNumberTableEntry)-sizeof(void*)));*/
-               void **calc;
-               lineNumberTableEntry *startEntry;
-
-               /*              printf("dataSeg: %p\n",dataSeg);*/
-               calc=dataSeg+LineNumberTableStart;
-               /*              printf("position of line number table start reference in data segment: %p\n",calc);
-                               printf("line number table start as found in table: %p\n",*calc);*/
-               ent=(lineNumberTableEntry *) (((char*)(*calc) - (sizeof(lineNumberTableEntry)-sizeof(void*))));
-               /*              printf("line number table start as calculated: %p\n",ent);*/
-               ent-=(lineNumberTableSize-1);
-               startEntry=ent;
-               /*              printf("line number table real start (bottom end) as calculated(2): %p\n",startEntry);*/
-
-               if (!fillInStackTrace_methodRecursive(buffer,method,startEntry,&ent,&lineNumberTableSize,adress)) {
-                       panic("Trace point not found in suspected method");
+               if (!stacktrace_fillInStackTrace_methodRecursive(buffer,
+                                                                                                                method,
+                                                                                                                lntentry,
+                                                                                                                lntsize,
+                                                                                                                pc)) {
+                       log_text("Trace point not found in suspected method");
+                       assert(0);
                }
        }
 }
 
 
-void  cacao_stacktrace_fillInStackTrace(void **target,CacaoStackTraceCollector coll)
+/* cacao_stacktrace_fillInStackTrace *******************************************
+
+   XXX
+
+*******************************************************************************/
+#ifdef ENABLE_JVMTI
+bool cacao_stacktrace_fillInStackTrace(void **target,
+                                                                          CacaoStackTraceCollector coll,
+                                                                          threadobject* thread)
+#else
+static bool cacao_stacktrace_fillInStackTrace(void **target,
+                                                                          CacaoStackTraceCollector coll)
+#endif
+
 {
+       stacktraceelement primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)];
+       stackTraceBuffer  buffer;
+       stackframeinfo   *sfi;
+       methodinfo       *m;
+       u1               *pv;
+       u1               *sp;
+       u4                framesize;
+       functionptr       ra;
+       functionptr       xpc;
+       bool              result;
+
+       /* prevent compiler warnings */
+
+       pv = NULL;
+       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)     */
+
+#ifdef ENABLE_JVMTI
+       if (thread == NULL) 
+               sfi = *STACKFRAMEINFO; /* invocation from Throwable */
+       else
+               sfi = thread->info._stackframeinfo; /* invocation from JVMTI */
+#else
+       sfi = *STACKFRAMEINFO;
+#endif
 
-       stacktraceelement primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)]; 
-               /*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*/
-       stackTraceBuffer buffer;
-       buffer.needsFree=0;
-       buffer.start=primaryBlock;
-       buffer.size=BLOCK_INITIALSIZE*sizeof(stacktraceelement);
-       buffer.full=0;
-
-
-       {
-               struct native_stackframeinfo *info=(*(((void**)(builtin_asm_get_stackframeinfo()))));
-               if (!info) {
-                       log_text("info ==0");
-                       *target=0;
-                       return;
-               } else {
-                       char *dataseg; /*make it byte addressable*/
-                       methodinfo *currentMethod=0;
-                       void *returnAdress;
-                       char* stackPtr;
+       if (!sfi) {
+               *target = NULL;
+               return true;
+       }
 
-/*                     utf_display(info->method->class->name);
-                       utf_display(info->method->name);*/
-                       
-                       while ((currentMethod!=0) ||  (info!=0)) {
-                               if (currentMethod==0) { /*some builtin native */
-                                       currentMethod=info->method;
-                                       returnAdress=info->returnToFromNative;
-                                       /*log_text("native");*/
-                                       if (currentMethod) {
-                                               /*utf_display(currentMethod->class->name);
-                                               utf_display(currentMethod->name);*/
-                                               addEntry(&buffer,currentMethod,0);
-                                       }
-#if defined(__ALPHA__)
-                                       if (info->savedpv!=0)
-                                               dataseg=info->savedpv;
-                                       else
-                                               dataseg=codegen_findmethod(returnAdress);
-#elif defined(__I386__)
-                                       dataseg=codegen_findmethod(returnAdress);
+#define PRINTMETHODS 0
+
+#if PRINTMETHODS
+       printf("\n\nfillInStackTrace start:\n");
+       fflush(stdout);
 #endif
-                                       currentMethod=(*((methodinfo**)(dataseg+MethodPointer)));
-                                       if (info->beginOfJavaStackframe==0)
-                                               stackPtr=((char*)info)+sizeof(native_stackframeinfo);
-                                       else
-#if defined(__ALPHA__)
-                                               stackPtr=(char*)(info->beginOfJavaStackframe);
-#elif defined(__I386__)
-                                               stackPtr=(char*)(info->beginOfJavaStackframe)+sizeof(void*);
+
+       /* loop while we have a method pointer (asm_calljavafunction has NULL) or */
+       /* there is a stackframeinfo in the chain                                 */
+
+       m = NULL;
+
+       while (m || sfi) {
+               /* m == NULL should only happen for the first time and inline         */
+               /* stackframe infos, like from the exception stubs or the patcher     */
+               /* wrapper                                                            */
+
+               if (m == NULL) {
+                       /* for native stub stackframe infos, pv is always NULL */
+
+                       if (sfi->pv == NULL) {
+                               /* get methodinfo, sp and ra from the current stackframe info */
+
+                               m  = sfi->method;
+                               sp = sfi->sp;           /* sp of parent Java function         */
+                               ra = sfi->ra;
+
+                               if (m)
+                                       addEntry(&buffer, m, 0);
+
+#if PRINTMETHODS
+                               utf_display_classname(m->class->name);
+                               printf(".");
+                               utf_display(m->name);
+                               utf_display(m->descriptor);
+                               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*) */
+
+                               pv = (u1 *) (ptrint) codegen_findmethod(ra);
+
+                               /* get methodinfo pointer from parent data segment */
+
+                               m = *((methodinfo **) (pv + MethodPointer));
+
+                       } else {
+                               /* Inline stackframe infos are special: they have a xpc of    */
+                               /* the actual exception position and the return address saved */
+                               /* since an inline stackframe info can also be in a leaf      */
+                               /* method (no return address saved on stack!!!).              */
+                               /* ATTENTION: This one is also for hardware exceptions!!!     */
+
+                               /* get methodinfo, sp and ra from the current stackframe info */
+
+                               m   = sfi->method;      /* m == NULL                          */
+                               pv  = sfi->pv;          /* pv of parent Java function         */
+                               sp  = sfi->sp;          /* sp of parent Java function         */
+                               ra  = sfi->ra;          /* ra of parent Java function         */
+                               xpc = sfi->xpc;         /* actual exception position          */
+
+#if PRINTMETHODS
+                               printf("NULL: inline stub\n");
+                               fflush(stdout);
 #endif
-                                       info=info->oldThreadspecificHeadValue;
-                               } else { /*method created by jit*/
-                                       u4 frameSize;
-                                       /*log_text("JIT");*/
-#if defined (__ALPHA__)
-                                       if (currentMethod->isleafmethod) {
-#ifdef JWDEBUG
-                                               printf("class.method:%s.%s\n",currentMethod->class->name->text,currentMethod->name->text);
+
+                               /* get methodinfo from current Java method */
+
+                               m = *((methodinfo **) (pv + MethodPointer));
+
+                               /* if m == NULL, this is a asm_calljavafunction call */
+
+                               if (m != NULL) {
+#if PRINTMETHODS
+                                       utf_display_classname(m->class->name);
+                                       printf(".");
+                                       utf_display(m->name);
+                                       utf_display(m->descriptor);
+                                       printf(": inline stub parent\n");
+                                       fflush(stdout);
 #endif
-                                               panic("How could that happen ??? A leaf method in the middle of a stacktrace ??");
-                                       }
+
+#if defined(ENABLE_INTRP)
+                                       if (!opt_intrp) {
 #endif
-                                       /*utf_display(currentMethod->class->name);
-                                       utf_display(currentMethod->name);*/
-                                       fillInStackTrace_method(&buffer,currentMethod,dataseg,returnAdress);
-                                       frameSize=*((u4*)(dataseg+FrameSize));
-#if defined(__ALPHA__)
-                                       /* cacao saves the return adress as the first element of the stack frame on alphas*/
-                                       dataseg=codegen_findmethod(*((void**)(stackPtr+frameSize-sizeof(void*))));
-                                       returnAdress=(*((void**)(stackPtr+frameSize-sizeof(void*))));
-#elif defined(__I386__)
-                                       /* on i386 the return adress is the first element before the stack frme*/
-                                       returnAdress=(*((void**)(stackPtr+frameSize)));
-                                       dataseg=codegen_findmethod(*((void**)(stackPtr+frameSize)));
+
+                                       /* add it to the stacktrace */
+
+                                       stacktrace_fillInStackTrace_method(&buffer, m, pv,
+                                                                                                          (u1 *) ((ptrint) xpc));
+
+                                       /* get the current stack frame size */
+
+                                       framesize = *((u4 *) (pv + FrameSize));
+
+                                       /* set stack pointer to stackframe of parent Java */
+                                       /* function of the current Java function */
+
+#if defined(__I386__) || defined (__X86_64__)
+                                       sp += framesize + SIZEOF_VOID_P;
+#else
+                                       sp += framesize;
 #endif
-/*                                     printf ("threadrootmethod %p\n",builtin_asm_get_threadrootmethod());
-                                       if (currentMethod==builtin_asm_get_threadrootmethod()) break;*/
-                                       currentMethod=(*((methodinfo**)(dataseg+MethodPointer)));
-#if defined(__ALPHA__)
-                                       stackPtr+=frameSize;
-#elif defined(__I386__)
-                                       stackPtr+=frameSize+sizeof(void*);
+
+                                       /* get data segment and methodinfo pointer from parent */
+                                       /* method */
+
+                                       pv = (u1 *) (ptrint) codegen_findmethod(ra);
+                                       m = *((methodinfo **) (pv + MethodPointer));
+
+#if defined(ENABLE_INTRP)
+                                       }
 #endif
                                }
+#if PRINTMETHODS
+                               else {
+                                       printf("asm_calljavafunction\n");
+                                       fflush(stdout);
+                               }
+#endif
                        }
-                       
-                       if (coll) coll(target,&buffer);
-                       if (buffer.needsFree) free(buffer.start);
-                       return;
+
+                       /* get previous stackframeinfo in the chain */
+
+                       sfi = sfi->prev;
+
+               } else {
+#if PRINTMETHODS
+                       utf_display_classname(m->class->name);
+                       printf(".");
+                       utf_display(m->name);
+                       utf_display(m->descriptor);
+                       printf(": JIT\n");
+#endif
+
+                       /* JIT method found, add it to the stacktrace (we subtract 1 from */
+                       /* the return address since it points the the instruction after */
+                       /* call) */
+
+                       stacktrace_fillInStackTrace_method(&buffer, m, pv,
+                                                                                          (u1 *) ((ptrint) ra) - 1);
+
+                       /* get the current stack frame size */
+
+                       framesize = *((u4 *) (pv + FrameSize));
+
+                       /* get return address of current stack frame */
+
+                       ra = md_stacktrace_get_returnaddress(sp, framesize);
+
+                       /* get data segment and methodinfo pointer from parent method */
+
+                       pv = (u1 *) (ptrint) codegen_findmethod(ra);
+                       m = *((methodinfo **) (pv + MethodPointer));
+
+                       /* walk the stack */
+
+#if defined(ENABLE_INTRP)
+                       if (opt_intrp)
+                               sp = *(u1 **)(sp - framesize);
+                       else
+#endif
+                               {
+#if defined(__I386__) || defined (__X86_64__)
+                                       sp += framesize + SIZEOF_VOID_P;
+#else
+                                       sp += framesize;
+#endif
+                               }
                }
-               /*log_text("\n=========================================================");*/
        }
-       *target=0;
+                       
+       if (coll)
+               result = coll(target, &buffer);
+
+       if (buffer.needsFree)
+               free(buffer.start);
 
+       return result;
 }
 
 
-static
-void stackTraceCollector(void **target, stackTraceBuffer *buffer) {
-       stackTraceBuffer *dest=*target=heap_allocate(sizeof(stackTraceBuffer)+buffer->full*sizeof(stacktraceelement),true,0);
-       memcpy(*target,buffer,sizeof(stackTraceBuffer));
-       memcpy(dest+1,buffer->start,buffer->full*sizeof(stacktraceelement));
+/* stackTraceCollector *********************************************************
 
-       dest->needsFree=0;
-       dest->size=dest->full;
-       dest->start=dest+1;
+   XXX
 
-       /*
-       if (buffer->full>0) {
-               printf("SOURCE BUFFER:%s\n",buffer->start[0].method->name->text);
-               printf("DEST BUFFER:%s\n",dest->start[0].method->name->text);
-       } else printf("Buffer is empty\n");
-       */
+*******************************************************************************/
+#ifdef ENABLE_JVMTI
+bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
+#else
+static bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
+#endif
+{
+       stackTraceBuffer *dest;
+
+       dest = *target = heap_allocate(sizeof(stackTraceBuffer) + buffer->full * sizeof(stacktraceelement), true, 0);
+
+       if (!dest)
+               return false;
+
+       memcpy(*target, buffer, sizeof(stackTraceBuffer));
+       memcpy(dest + 1, buffer->start, buffer->full * sizeof(stacktraceelement));
+
+       dest->needsFree = 0;
+       dest->size = dest->full;
+       dest->start = (stacktraceelement *) (dest + 1);
+
+       return true;
 }
 
 
-void  cacao_stacktrace_NormalTrace(void **target) {
-       cacao_stacktrace_fillInStackTrace(target,&stackTraceCollector);
+bool cacao_stacktrace_NormalTrace(void **target)
+{
+#ifdef ENABLE_JVMTI
+       return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector, NULL);
+#else
+       return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector);
+#endif
+
 }
 
 
 
-static
-void classContextCollector(void **target, stackTraceBuffer *buffer) {
-        java_objectarray *tmpArray;
-        int i;
-        stacktraceelement *current;
-        stacktraceelement *start;
-        classinfo *c;
-        size_t size;
+static bool classContextCollector(void **target, stackTraceBuffer *buffer)
+{
+       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++;
 
-       size=buffer->full;
-       targetSize=0;
-       for (i=0;i<size;i++)
-               if (buffer->start[i].method!=0) targetSize++;
-       start=buffer->start;
+       start = buffer->start;
        start++;
        targetSize--;
 
-        if (targetSize > 0) {
-                if ((start->method) && (start->method->class== class_java_lang_SecurityManager)) {
-                        targetSize--;
-                        start++;
-                }
-        }
-
-        tmpArray =
-                builtin_newarray(targetSize, class_array_of(class_java_lang_Class)->vftbl);
-
-        for(i = 0, current = start; i < targetSize; i++, current++) {
-                if (current->method==0) { i--; continue;}
-               /*printf("adding item to class context array:%s\n",current->method->class->name->text);
-               printf("method for class: :%s\n",current->method->name->text);*/
-                use_class_as_object(current->method->class);
-                tmpArray->data[i] = (java_objectheader *) current->method->class;
-        }
-
-        *target=tmpArray;
+       if (targetSize > 0) {
+               if (start->method &&
+                       (start->method->class == class_java_lang_SecurityManager)) {
+                       targetSize--;
+                       start++;
+               }
+       }
+
+       oa = builtin_anewarray(targetSize, class_java_lang_Class);
+
+       if (!oa)
+               return false;
+
+       for(i = 0, current = start; i < targetSize; i++, current++) {
+               if (!current->method) {
+                       i--;
+                       continue;
+               }
+
+               use_class_as_object(current->method->class);
+
+               oa->data[i] = (java_objectheader *) current->method->class;
+       }
+
+       *target = oa;
+
+       return true;
 }
 
 
 
-java_objectarray *cacao_createClassContextArray() {
-       java_objectarray *array=0;
-       cacao_stacktrace_fillInStackTrace(&array,&classContextCollector);
+java_objectarray *cacao_createClassContextArray(void)
+{
+       java_objectarray *array = NULL;
+
+#ifdef ENABLE_JVMTI
+       if (!cacao_stacktrace_fillInStackTrace((void **) &array,
+                                                                                  &classContextCollector, NULL))
+#else
+       if (!cacao_stacktrace_fillInStackTrace((void **) &array,
+                                                                                  &classContextCollector))
+#endif
+               return NULL;
+
        return array;
-       
 }
 
 
-static
-void classLoaderCollector(void **target, stackTraceBuffer *buffer) {
-        int i;
-        stacktraceelement *current;
-        stacktraceelement *start;
-        methodinfo *m;
-        classinfo *privilegedAction;
-        size_t size;
-
-        size = buffer->full;
-
-        if (size > 1) {
-               size--;
-               start=&(buffer->start[1]);
-                if (start == class_java_lang_SecurityManager) {
-                        size--;
-                        start--;
-                }
-        } else {
-               start=0;
-               size=0;
-       }
-        privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
+/* stacktrace_classLoaderCollector *********************************************
+
+   XXX
+
+*******************************************************************************/
+
+static bool stacktrace_classLoaderCollector(void **target,
+                                                                                       stackTraceBuffer *buffer)
+{
+       stacktraceelement *current;
+       stacktraceelement *start;
+       methodinfo        *m;
+       ptrint             size;
+       s4                 i;
 
-        for(i=0, current = start; i < size; i++, current++) {
-                m=start->method;
-               if (!m) continue;
+       size = buffer->full;
+       start = &(buffer->start[0]);
 
-                if (m->class == privilegedAction) {
-                       *target=NULL;
-                        return;
+       for(i = 0, current = start; i < size; i++, current++) {
+               m = current->method;
+
+               if (!m)
+                       continue;
+
+               if (m->class == class_java_security_PrivilegedAction) {
+                       *target = NULL;
+                       return true;
                }
 
-                if (m->class->classloader) {
-                        *target= (java_lang_ClassLoader *) m->class->classloader;
-                       return;
+               if (m->class->classloader) {
+                       *target = (java_lang_ClassLoader *) m->class->classloader;
+                       return true;
                }
-        }
+       }
+
+       *target = NULL;
 
-        *target=NULL;
+       return true;
 }
 
-java_objectheader *cacao_currentClassLoader() {
-       java_objectheader *header=0;
-       cacao_stacktrace_fillInStackTrace(&header,&classLoaderCollector);
+
+/* cacao_currentClassLoader ****************************************************
+
+   XXX
+
+*******************************************************************************/
+
+java_objectheader *cacao_currentClassLoader(void)
+{
+       java_objectheader *header = NULL;
+
+
+#ifdef ENABLE_JVMTI
+       if (!cacao_stacktrace_fillInStackTrace((void**)&header,
+                                                                                  &stacktrace_classLoaderCollector,
+                                                                                  NULL))
+#else
+       if (!cacao_stacktrace_fillInStackTrace((void**)&header,
+                                                                                  &stacktrace_classLoaderCollector))
+#endif
+               return NULL;
+
        return header;
 }
 
 
-static
-void callingMethodCollector(void **target, stackTraceBuffer *buffer) { 
-        if (buffer->full >2) (*target)=buffer->start[2].method;
-       else (*target=0);
+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;
+
+/*     *result = (java_objectarray **) target; */
+
+       size = buffer->full;
+
+       oa = builtin_anewarray(2, arrayclass_java_lang_Object);
+
+       if (!oa)
+               return false;
+
+       classes = builtin_anewarray(size, class_java_lang_Class);
+
+       if (!classes)
+               return false;
+
+       methodnames = builtin_anewarray(size, class_java_lang_String);
+
+       if (!methodnames)
+               return false;
+
+       oa->data[0] = (java_objectheader *) classes;
+       oa->data[1] = (java_objectheader *) methodnames;
+
+       for (i = 0, current = &(buffer->start[0]); i < size; i++, current++) {
+               c = current->method->class;
+
+               use_class_as_object(c);
+
+               classes->data[i] = (java_objectheader *) c;
+               str = javastring_new(current->method->name);
+
+               if (!str)
+                       return false;
+
+               methodnames->data[i] = (java_objectheader *) str;
+       }
+
+       *target = oa;
+
+       return true;
 }
 
-methodinfo *cacao_callingMethod() {
-       methodinfo *method;
-       cacao_stacktrace_fillInStackTrace(&method,&callingMethodCollector);
-       return method;
+
+java_objectarray *cacao_getStackForVMAccessController(void)
+{
+       java_objectarray *result = NULL;
+
+#ifdef ENABLE_JVMTI
+       if (!cacao_stacktrace_fillInStackTrace((void **) &result,
+                                                                                  &getStackCollector,NULL))
+#else
+       if (!cacao_stacktrace_fillInStackTrace((void **) &result,
+                                                                                  &getStackCollector))
+#endif
+               return NULL;
+
+       return result;
+}
+
+
+/* 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(buffer);
+
+       } else {
+               puts("\t<<No stacktrace available>>");
+               fflush(stdout);
+       }
+}
+
+
+/* stacktrace_print_trace ******************************************************
+
+   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.
+
+*******************************************************************************/
+
+void stacktrace_print_trace(stackTraceBuffer *stb)
+{
+       stacktraceelement *ste;
+       methodinfo        *m;
+       s4                 i;
+
+       ste = stb->start;
+
+       for (i = 0; i < stb->size; i++, ste++) {
+               m = ste->method;
+
+               printf("\tat ");
+               utf_display_classname(m->class->name);
+               printf(".");
+               utf_display(m->name);
+               utf_display(m->descriptor);
+
+               if (m->flags & ACC_NATIVE) {
+                       puts("(Native Method)");
+
+               } else {
+                       printf("(");
+                       utf_display(m->class->sourcefile);
+                       printf(":%d)\n", (u4) ste->linenumber);
+               }
+       }
+
+       /* just to be sure */
+
+       fflush(stdout);
 }
 
+
 /*
  * 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