* src/vm/class.c [ENABLE_JAVASE] (arrayclass_java_lang_Object): Added
[cacao.git] / src / vm / jit / stacktrace.c
index 63d8d0b1298631b0f6672b0abac54583b48a80ae..beaae0c7716fec52f9a7d2ee8d01309758daa8d7 100644 (file)
@@ -1,4 +1,4 @@
-/* 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,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    Contact: cacao@cacaojvm.org
 
    Authors: Joseph Wenninger
-
-   Changes: Christian Thalinger
+            Christian Thalinger
             Edwin Steiner
 
-   $Id: stacktrace.c 4921 2006-05-15 14:24:36Z twisti $
+   $Id: stacktrace.c 6251 2006-12-27 23:15:56Z twisti $
 
 */
 
 
 #include "vm/types.h"
 
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "mm/memory.h"
 #include "native/native.h"
 
 #include "vm/global.h"                   /* required here for native includes */
-#include "native/include/java_lang_ClassLoader.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"
 #include "vm/cycles-stats.h"
 
 
-/* linenumbertable_entry ******************************************************/
-
-/* Keep the type of line the same as the pointer type, otherwise we
-   run into alignment troubles (like on MIPS64). */
-
-typedef struct linenumbertable_entry linenumbertable_entry;
-
-struct linenumbertable_entry {
-       ptrint  line;               /* NOTE: see doc/inlining_stacktrace.txt for  */
-       u1     *pc;                 /*       special meanings of line and pc.     */
-};
-
 /* global variables ***********************************************************/
 
 #if !defined(ENABLE_THREADS)
@@ -109,6 +98,7 @@ void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
 {
        stackframeinfo **psfi;
        methodinfo      *m;
+       codeinfo        *code;
 
        /* get current stackframe info pointer */
 
@@ -119,19 +109,23 @@ void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
        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 */
 
-       m = *((methodinfo **) (pv + MethodPointer));
+       code = *((codeinfo **) (pv + CodeinfoPointer));
+
+       /* For asm_vm_call_method the codeinfo pointer is NULL. */
+
+       m = (code == NULL) ? NULL : code->m;
 
        /* fill new stackframe info structure */
 
@@ -172,7 +166,7 @@ void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
                /* if we don't have pv handy */
 
                if (pv == NULL)
-                       pv = codegen_findmethod(ra);
+                       pv = codegen_get_pv_from_pc(ra);
 
        }
 #endif
@@ -220,12 +214,12 @@ 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);
+                               pv = md_codegen_get_pv_from_pc(ra);
 #endif
                        }
        }
@@ -288,10 +282,15 @@ void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 {
        stackframeinfo **psfi;
        methodinfo      *m;
+       codeinfo        *code;
 
-       /* get methodinfo pointer from data segment */
+       /* get codeinfo pointer from 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;
 
        /* get current stackframe info pointer */
 
@@ -314,7 +313,7 @@ void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
 
 /* stacktrace_remove_stackframeinfo ********************************************
 
-   XXX
+   Remove the topmost stackframeinfo in the current thread.
 
 *******************************************************************************/
 
@@ -409,7 +408,7 @@ java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
 
        /* create exception */
 
-       o = new_arraystoreexception();
+       o = exceptions_new_arraystoreexception();
 
        /* remove stackframeinfo */
 
@@ -426,10 +425,11 @@ java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
 *******************************************************************************/
 
 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
-                                                                                                               u1 *xpc)
+                                                                                                               u1 *xpc,
+                                                                                                               java_objectheader *o)
 {
        stackframeinfo     sfi;
-       java_objectheader *o;
+       java_objectheader *e;
 
        /* create stackframeinfo */
 
@@ -437,13 +437,13 @@ java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
 
        /* create exception */
 
-       o = new_classcastexception();
+       e = exceptions_new_classcastexception(o);
 
        /* remove stackframeinfo */
 
        stacktrace_remove_stackframeinfo(&sfi);
 
-       return o;
+       return e;
 }
 
 
@@ -465,7 +465,7 @@ java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
 
        /* create exception */
 
-       o = new_nullpointerexception();
+       o = exceptions_new_nullpointerexception();
 
        /* remove stackframeinfo */
 
@@ -504,9 +504,17 @@ java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
 
        /* resolve methodinfo pointer from exception object */
 
+#if defined(ENABLE_JAVASE)
        m = class_resolvemethod(o->vftbl->class,
                                                        utf_fillInStackTrace,
                                                        utf_void__java_lang_Throwable);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+       m = class_resolvemethod(o->vftbl->class,
+                                                       utf_fillInStackTrace,
+                                                       utf_void__void);
+#else
+#error IMPLEMENT ME!
+#endif
 
        /* call function */
 
@@ -566,7 +574,7 @@ java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
 
        /* create exception */
 
-       o = new_nullpointerexception();
+       o = exceptions_new_nullpointerexception();
 
        /* remove stackframeinfo */
 
@@ -612,94 +620,6 @@ static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
 }
 
 
-/* stacktrace_add_method_intern ************************************************
-
-   This function is used by stacktrace_add_method to search the line number
-   table for the line corresponding to a given pc. The function recurses for
-   inlined methods.
-
-*******************************************************************************/
-
-static bool stacktrace_add_method_intern(stacktracebuffer *stb, 
-                                                                                methodinfo *m, 
-                                                                                linenumbertable_entry *lntentry,
-                                                                                ptrint lntsize,
-                                                                                u1 *pc)
-{
-       linenumbertable_entry *lntinline;   /* special entry for inlined method */
-
-       assert(stb);
-       assert(lntentry);
-
-       /* Find the line number for the specified PC (going backwards
-          in the linenumber table). The linenumber table size is zero
-          in native stubs. */
-
-       for (; lntsize > 0; lntsize--, lntentry--) {
-
-               /* did we reach the current line? */
-
-               /* Note: In case of inlining this may actually compare the pc
-                  against a methodinfo *, yielding a non-sensical
-                  result. This is no problem, however, as we ignore such
-                  entries in the switch below. This way we optimize for the
-                  common case (ie. a real pc in lntentry->pc). */
-
-               if (pc >= lntentry->pc) {
-
-                       /* check for special inline entries (see
-                          doc/inlining_stacktrace.txt for details */
-
-                       if ((s4)lntentry->line < 0) {
-                               switch (lntentry->line) {
-                                       case -1: 
-                                               /* begin of inlined method (ie. INLINE_END
-                                                  instruction) */
-
-                                               lntinline = --lntentry;/* get entry with methodinfo * */
-                                               lntentry--;            /* skip the special entry      */
-                                               lntsize -= 2;
-
-                                               /* search inside the inlined method */
-                                               if (stacktrace_add_method_intern(
-                                                                       stb, 
-                                                                       (methodinfo*) lntinline->pc,
-                                                                       lntentry,
-                                                                       lntsize,
-                                                                       pc))
-                                               {
-                                                       /* the inlined method contained the pc */
-                                                       assert(lntinline->line <= -3);
-                                                       stacktrace_add_entry(stb, m, (-3) - lntinline->line);
-                                                       return true;
-                                               }
-                                               /* pc was not in inlined method, continue
-                                                  search.  Entries inside the inlined method
-                                                  will be skipped because their lntentry->pc
-                                                  is higher than pc.  */
-                                               break;
-
-                                       case -2: 
-                                               /* end of inlined method */
-                                               return false;
-
-                                       /* default: is only reached for an -3-line entry
-                                          after a skipped -2 entry. We can safely ignore
-                                          it and continue searching.  */
-                               }
-                       }
-                       else {
-                               /* found a normal entry */
-                               stacktrace_add_entry(stb, m, lntentry->line);
-                               return true;
-                       }
-               }
-       }
-
-       /* not found */
-       return false;
-}
-
 /* stacktrace_add_method *******************************************************
 
    Add stacktrace entries[1] for the given method to the stacktrace buffer.
@@ -721,54 +641,20 @@ static bool stacktrace_add_method_intern(stacktracebuffer *stb,
 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     */
-
-       /* 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 = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
-
-       /* find the realization of the method the pc is in    */
-       /* XXX Note: This is preliminary. It would be cleaner */
-       /* to get the codeinfo * from the PV                  */
-
-       code = m->code;
-       while (1) {
-               if (!code) {
-#ifndef NDEBUG
-                       method_println(m);
-                       dolog("Could not find codeinfo for Current PC: %p",(void*)pc);
-#endif
-                       abort();
-               }
+       codeinfo *code;                     /* compiled realization of method     */
+       s4        linenumber;
 
-               if (((ptrint)pc >= (ptrint)code->entrypoint)
-                               &&
-                       ( (pc - (u1*)code->entrypoint) < code->mcodelength ))
-               {
-                       /* found */
-                       break;
-               }
+       /* find the realization of the method the pc is in */
 
-               code = code->prev;
-       }
+       code = *((codeinfo **) (pv + CodeinfoPointer));
 
        /* search the line number table */
 
-       if (stacktrace_add_method_intern(stb, m, lntentry, lntsize, pc))
-               return true;
+       linenumber = dseg_get_linenumber_from_pc(&m, pv, pc);
 
-       /* If we get here, just add the entry with line number 0. */
+       /* now add a new entry to the staktrace */
 
-       stacktrace_add_entry(stb, m, 0);
+       stacktrace_add_entry(stb, m, linenumber);
 
        return true;
 }
@@ -791,6 +677,7 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
        stacktracebuffer *stb;
        stackframeinfo   *sfi;
        methodinfo       *m;
+       codeinfo         *code;
        u1               *pv;
        u1               *sp;
        u4                framesize;
@@ -836,7 +723,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. */
@@ -866,18 +753,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
@@ -903,7 +795,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 */
 
@@ -932,8 +829,8 @@ 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__)
                                        sp += framesize + SIZEOF_VOID_P;
@@ -941,14 +838,19 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
                                        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)
                                        }
@@ -1007,16 +909,20 @@ 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
                                }
 
-                       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 */
 
@@ -1048,11 +954,12 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
 
 *******************************************************************************/
 
-stacktracebuffer *stacktrace_fillInStackTrace(void)
+stacktracecontainer *stacktrace_fillInStackTrace(void)
 {
-       stacktracebuffer *stb;
-       stacktracebuffer *gcstb;
-       s4                dumpsize;
+       stacktracebuffer    *stb;
+       stacktracecontainer *gcstc;
+       s4                   gcstc_size;
+       s4                   dumpsize;
        CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
 
        /* mark start of dump memory area */
@@ -1066,20 +973,21 @@ stacktracebuffer *stacktrace_fillInStackTrace(void)
                goto return_NULL;
 
        /* allocate memory from the GC heap and copy the stacktrace buffer */
+       /* ATTENTION: use stacktracecontainer for this and make it look like
+       an array */
 
-       gcstb = GCNEW(stacktracebuffer);
+       gcstc_size = sizeof(stacktracebuffer) +
+                    sizeof(stacktrace_entry) * stb->used;
+       gcstc = (stacktracecontainer *) builtin_newarray_byte(gcstc_size);
 
-       if (gcstb == NULL)
+       if (gcstc == NULL)
                goto return_NULL;
 
-       gcstb->capacity = stb->capacity;
-       gcstb->used     = stb->used;
-       gcstb->entries  = GCMNEW(stacktrace_entry, stb->used);
-
-       if (gcstb->entries == NULL)
-               goto return_NULL;
+       gcstc->stb.capacity = stb->capacity;
+       gcstc->stb.used     = stb->used;
+       gcstc->stb.entries  = gcstc->data;
 
-       MCOPY(gcstb->entries, stb->entries, stacktrace_entry, stb->used);
+       MCOPY(gcstc->data, stb->entries, stacktrace_entry, stb->used);
 
        /* release dump memory */
 
@@ -1087,7 +995,7 @@ stacktracebuffer *stacktrace_fillInStackTrace(void)
 
        CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
                                                                   stacktrace_overhead)
-       return gcstb;
+       return gcstc;
 
 return_NULL:
        dump_release(dumpsize);
@@ -1193,6 +1101,7 @@ return_NULL:
 
 *******************************************************************************/
 
+#if defined(ENABLE_JAVASE)
 classinfo *stacktrace_getCurrentClass(void)
 {
        stacktracebuffer  *stb;
@@ -1242,6 +1151,7 @@ return_NULL:
 
        return NULL;
 }
+#endif /* ENABLE_JAVASE */
 
 
 /* stacktrace_getStack *********************************************************
@@ -1254,6 +1164,7 @@ return_NULL:
 
 *******************************************************************************/
 
+#if defined(ENABLE_JAVASE)
 java_objectarray *stacktrace_getStack(void)
 {
        stacktracebuffer *stb;
@@ -1274,7 +1185,8 @@ java_objectarray *stacktrace_getStack(void)
        /* create a stacktrace for the current thread */
 
        stb = stacktrace_create(THREADOBJECT);
-       if (!stb)
+
+       if (stb == NULL)
                goto return_NULL;
 
        /* get the first stacktrace entry */
@@ -1285,17 +1197,17 @@ java_objectarray *stacktrace_getStack(void)
 
        oa = builtin_anewarray(2, arrayclass_java_lang_Object);
 
-       if (!oa)
+       if (oa == NULL)
                goto return_NULL;
 
        classes = builtin_anewarray(stb->used, class_java_lang_Class);
 
-       if (!classes)
+       if (classes == NULL)
                goto return_NULL;
 
        methodnames = builtin_anewarray(stb->used, class_java_lang_String);
 
-       if (!methodnames)
+       if (methodnames == NULL)
                goto return_NULL;
 
        /* set up the 2-dimensional array */
@@ -1311,7 +1223,7 @@ java_objectarray *stacktrace_getStack(void)
                classes->data[i] = (java_objectheader *) c;
                str = javastring_new(ste->method->name);
 
-               if (!str)
+               if (str == NULL)
                        goto return_NULL;
 
                methodnames->data[i] = (java_objectheader *) str;
@@ -1332,6 +1244,7 @@ return_NULL:
 
        return NULL;
 }
+#endif /* ENABLE_JAVASE */
 
 
 /* stacktrace_print_trace_from_buffer ******************************************
@@ -1342,7 +1255,7 @@ return_NULL:
 
 *******************************************************************************/
 
-static void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
+void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
 {
        stacktrace_entry *ste;
        methodinfo       *m;
@@ -1382,7 +1295,7 @@ static void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
 
 *******************************************************************************/
 
-void stacktrace_dump_trace(void)
+void stacktrace_dump_trace(threadobject *thread)
 {
        stacktracebuffer *stb;
        s4                dumpsize;
@@ -1415,14 +1328,13 @@ void stacktrace_dump_trace(void)
 
        /* create a stacktrace for the current thread */
 
-       stb = stacktrace_create(THREADOBJECT);
+       stb = stacktrace_create(thread);
 
        /* print stacktrace */
 
-       if (stb) {
+       if (stb)
                stacktrace_print_trace_from_buffer(stb);
-
-       } else {
+       else {
                puts("\t<<No stacktrace available>>");
                fflush(stdout);
        }
@@ -1441,7 +1353,10 @@ void stacktrace_dump_trace(void)
 void stacktrace_print_trace(java_objectheader *xptr)
 {
        java_lang_Throwable   *t;
+#if defined(WITH_CLASSPATH_GNU)
        java_lang_VMThrowable *vmt;
+#endif
+       stacktracecontainer   *stc;
        stacktracebuffer      *stb;
 
        t = (java_lang_Throwable *) xptr;
@@ -1451,8 +1366,14 @@ void stacktrace_print_trace(java_objectheader *xptr)
 
        /* now print the stacktrace */
 
+#if defined(WITH_CLASSPATH_GNU)
        vmt = t->vmState;
-       stb = (stacktracebuffer *) vmt->vmData;
+       stc = (stacktracecontainer *) vmt->vmData;
+       stb = &(stc->stb);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       stc = (stacktracecontainer *) t->backtrace;
+       stb = &(stc->stb);
+#endif
 
        stacktrace_print_trace_from_buffer(stb);
 }