* src/native/jni.c (_Jv_JNI_FindClass): Renamed to jni_FindClass, call
[cacao.git] / src / vm / exceptions.c
index d303ef80d5833e77994aa18f71844157b36ad645..2b3f71ba8eb52a82de096d86b3e03c9290824369 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/exceptions.c - exception related functions
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -31,7 +29,6 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <sys/mman.h>
 
 #include "vm/types.h"
 #include "native/native.h"
 
 #include "native/include/java_lang_String.h"
+#include "native/include/java_lang_Thread.h"
 #include "native/include/java_lang_Throwable.h"
 
 #include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
 
 #include "toolbox/util.h"
 
@@ -70,6 +68,7 @@
 #include "vmcore/loader.h"
 #include "vmcore/method.h"
 #include "vmcore/options.h"
+#include "vmcore/system.h"
 
 #if defined(ENABLE_VMLOG)
 #include <vmlog_cacao.h>
@@ -100,11 +99,13 @@ void exceptions_init(void)
        /* mmap a memory page at address 0x0, so our hardware-exceptions
           work. */
 
-       pagesize = getpagesize();
+       pagesize = system_getpagesize();
 
-       (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+       (void) system_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
 #endif
 
+       TRACESUBSYSTEMINITIALIZATION("exceptions_init");
+
        /* check if we get into trouble with our hardware-exceptions */
 
        if (OFFSET(java_bytearray_t, data) <= EXCEPTION_HARDWARE_LARGEST)
@@ -276,6 +277,44 @@ static void exceptions_abort(utf *classname, utf *message)
 }
 
 
+/* exceptions_new_class_utf ****************************************************
+
+   Creates an exception object with the given class and initalizes it
+   with the given utf message.
+
+   IN:
+      c ......... exception class
+         message ... the message as an utf *
+
+   RETURN VALUE:
+     an exception pointer (in any case -- either it is the newly
+     created exception, or an exception thrown while trying to create
+     it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
+{
+       java_handle_t *s;
+       java_handle_t *o;
+
+       if (vm_initializing)
+               exceptions_abort(c->name, message);
+
+       s = javastring_new(message);
+
+       if (s == NULL)
+               return exceptions_get_exception();
+
+       o = native_new_and_init_string(c, s);
+
+       if (o == NULL)
+               return exceptions_get_exception();
+
+       return o;
+}
+
+
 /* exceptions_new_utf **********************************************************
 
    Creates an exception object with the given name and initalizes it.
@@ -307,6 +346,99 @@ static java_handle_t *exceptions_new_utf(utf *classname)
 }
 
 
+/* exceptions_new_utf_javastring ***********************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/String message.
+
+   IN:
+      classname....class name in UTF-8
+         message......the message as a java.lang.String
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_javastring(utf *classname,
+                                                                                                       java_handle_t *message)
+{
+       java_handle_t *o;
+       classinfo     *c;
+   
+       if (vm_initializing)
+               exceptions_abort(classname, NULL);
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return exceptions_get_exception();
+
+       o = native_new_and_init_string(c, message);
+
+       if (o == NULL)
+               return exceptions_get_exception();
+
+       return o;
+}
+
+
+/* exceptions_new_utf_utf ******************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given utf message.
+
+   IN:
+      classname....class name in UTF-8
+         message......the message as an utf *
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
+{
+       classinfo     *c;
+       java_handle_t *o;
+
+       if (vm_initializing)
+               exceptions_abort(classname, message);
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return exceptions_get_exception();
+
+       o = exceptions_new_class_utf(c, message);
+
+       return o;
+}
+
+
+/* exceptions_throw_class_utf **************************************************
+
+   Creates an exception object with the given class, initalizes and
+   throws it with the given utf message.
+
+   IN:
+      c ......... exception class
+         message ... the message as an utf *
+
+*******************************************************************************/
+
+static void exceptions_throw_class_utf(classinfo *c, utf *message)
+{
+       java_handle_t *o;
+
+       o = exceptions_new_class_utf(c, message);
+
+       exceptions_set_exception(o);
+}
+
+
 /* exceptions_throw_utf ********************************************************
 
    Creates an exception object with the given name, initalizes and
@@ -501,87 +633,6 @@ static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
 }
 
 
-/* exceptions_new_utf_javastring ***********************************************
-
-   Creates an exception object with the given name and initalizes it
-   with the given java/lang/String message.
-
-   IN:
-      classname....class name in UTF-8
-         message......the message as a java.lang.String
-
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_javastring(utf *classname,
-                                                                                                       java_handle_t *message)
-{
-       java_handle_t *o;
-       classinfo     *c;
-   
-       if (vm_initializing)
-               exceptions_abort(classname, NULL);
-
-       c = load_class_bootstrap(classname);
-
-       if (c == NULL)
-               return exceptions_get_exception();
-
-       o = native_new_and_init_string(c, message);
-
-       if (o == NULL)
-               return exceptions_get_exception();
-
-       return o;
-}
-
-
-/* exceptions_new_utf_utf ******************************************************
-
-   Creates an exception object with the given name and initalizes it
-   with the given utf message.
-
-   IN:
-      classname....class name in UTF-8
-         message......the message as an utf *
-
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
-{
-       classinfo     *c;
-       java_handle_t *s;
-       java_handle_t *o;
-
-       if (vm_initializing)
-               exceptions_abort(classname, message);
-
-       c = load_class_bootstrap(classname);
-
-       if (c == NULL)
-               return exceptions_get_exception();
-
-       s = javastring_new(message);
-
-       if (s == NULL)
-               return exceptions_get_exception();
-
-       o = native_new_and_init_string(c, s);
-
-       if (o == NULL)
-               return exceptions_get_exception();
-
-       return o;
-}
-
-
 /* exceptions_throw_utf_utf ****************************************************
 
    Creates an exception object with the given name, initalizes and
@@ -646,9 +697,9 @@ static java_handle_t *exceptions_new_error(utf *message)
 
 java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
 {
-       stackframeinfo  sfi;
-       java_handle_t  *e;
-       java_object_t  *o;
+       stackframeinfo_t  sfi;
+       java_handle_t    *e;
+       java_object_t    *o;
 
        /* Fill and add a stackframeinfo (XPC is equal to RA). */
 
@@ -794,7 +845,7 @@ void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
 
 void exceptions_throw_classnotfoundexception(utf *name)
 {      
-       exceptions_throw_utf_utf(utf_java_lang_ClassNotFoundException, name);
+       exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
 }
 
 
@@ -1589,60 +1640,6 @@ void exceptions_throw_stringindexoutofboundsexception(void)
 }
 
 
-/* exceptions_classnotfoundexception_to_noclassdeffounderror *******************
-
-   Check the exception for a ClassNotFoundException. If it is one,
-   convert it to a NoClassDefFoundError.
-
-*******************************************************************************/
-
-void exceptions_classnotfoundexception_to_noclassdeffounderror(void)
-{
-       classinfo           *c;
-       java_handle_t       *o;
-       java_handle_t       *cause;
-       java_lang_Throwable *object;
-       java_lang_String    *s;
-
-       /* Load java/lang/ClassNotFoundException for the instanceof
-          check. */
-
-       c = load_class_bootstrap(utf_java_lang_ClassNotFoundException);
-
-       if (c == NULL)
-               return;
-
-       /* Get the cause. */
-
-       cause = exceptions_get_exception();
-
-       /* Convert ClassNotFoundException's to NoClassDefFoundError's. */
-
-       if (builtin_instanceof(cause, c)) {
-               /* clear exception, because we are calling jit code again */
-
-               exceptions_clear_exception();
-
-               /* create new error */
-
-               object = (java_lang_Throwable *) cause;
-               LLNI_field_get_ref(object, detailMessage, s);
-
-               o = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
-                                                                                 (java_handle_t *) s);
-
-               /* we had an exception while creating the error */
-
-               if (exceptions_get_exception())
-                       return;
-
-               /* set new exception */
-
-               exceptions_set_exception(o);
-       }
-}
-
-
 /* exceptions_fillinstacktrace *************************************************
 
    Calls the fillInStackTrace-method of the currently thrown
@@ -1707,26 +1704,25 @@ java_handle_t *exceptions_fillinstacktrace(void)
 *******************************************************************************/
 
 #if defined(ENABLE_JIT)
-u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
+void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
 {
-       stackframeinfo         sfi;
-       java_handle_t         *xptr;
-       methodinfo            *m;
-       codeinfo              *code;
-       s4                     issync;
-       dseg_exception_entry  *ex;
-       s4                     exceptiontablelength;
-       s4                     i;
-       classref_or_classinfo  cr;
-       classinfo             *c;
+       stackframeinfo_t        sfi;
+       java_handle_t          *xptr;
+       methodinfo             *m;
+       codeinfo               *code;
+       exceptiontable_t       *et;
+       exceptiontable_entry_t *ete;
+       s4                      i;
+       classref_or_classinfo   cr;
+       classinfo              *c;
 #if defined(ENABLE_THREADS)
-       java_object_t         *o;
+       java_object_t          *o;
 #endif
-       u1                    *result;
+       void                   *result;
 
 #ifdef __S390__
        /* Addresses are 31 bit integers */
-#      define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF)
+#      define ADDR_MASK(x) (void *) ((uintptr_t) (x) & 0x7FFFFFFF)
 #else
 #      define ADDR_MASK(x) (x)
 #endif
@@ -1740,17 +1736,20 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
 
        result = NULL;
 
-       /* get info from the method header */
+       /* Get the codeinfo for the current method. */
 
-       code                 = *((codeinfo **)            (pv + CodeinfoPointer));
-       issync               = *((s4 *)                   (pv + IsSync));
-       ex                   =   (dseg_exception_entry *) (pv + ExTableStart);
-       exceptiontablelength = *((s4 *)                   (pv + ExTableSize));
+       code = code_get_codeinfo_for_pv(pv);
 
        /* Get the methodinfo pointer from the codeinfo pointer. For
-          asm_vm_call_method the codeinfo pointer is NULL. */
+          asm_vm_call_method the codeinfo pointer is NULL and we simply
+          can return the proper exception handler. */
 
-       m = (code == NULL) ? NULL : code->m;
+       if (code == NULL) {
+               result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
+               goto exceptions_handle_exception_return;
+       }
+
+       m = code->m;
 
 #if !defined(NDEBUG)
        /* print exception trace */
@@ -1763,25 +1762,20 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
 # endif
 #endif
 
-       for (i = 0; i < exceptiontablelength; i++) {
-               /* ATTENTION: keep this here, as we need to decrement the
-           pointer before the loop executes! */
+       /* Get the exception table. */
 
-               ex--;
+       et = code->exceptiontable;
 
-               /* If the start and end PC is NULL, this means we have the
-                  special case of asm_vm_call_method.  So, just return the
-                  proper exception handler. */
+       if (et != NULL) {
+       /* Iterate over all exception table entries. */
 
-               if ((ex->startpc == NULL) && (ex->endpc == NULL)) {
-                       result = (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
-                       goto exceptions_handle_exception_return;
-               }
+       ete = et->entries;
 
+       for (i = 0; i < et->length; i++, ete++) {
                /* is the xpc is the current catch range */
 
-               if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) {
-                       cr = ex->catchtype;
+               if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) {
+                       cr = ete->catchtype;
 
                        /* NULL catches everything */
 
@@ -1795,11 +1789,11 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
 
                                if (opt_TraceExceptions) {
                                        exceptions_print_exception(xptr);
-                                       stacktrace_print_trace(xptr);
+                                       stacktrace_print_exception(xptr);
                                }
 #endif
 
-                               result = ex->handlerpc;
+                               result = ete->handlerpc;
                                goto exceptions_handle_exception_return;
                        }
 
@@ -1807,13 +1801,14 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
 
                        if (IS_CLASSREF(cr)) {
                                /* The exception class reference is unresolved. */
-                               /* We have to do _eager_ resolving here. While the class of */
-                               /* the exception object is guaranteed to be loaded, it may  */
-                               /* well have been loaded by a different loader than the     */
-                               /* defining loader of m's class, which is the one we must   */
-                               /* use to resolve the catch class. Thus lazy resolving      */
-                               /* might fail, even if the result of the resolution would   */
-                               /* be an already loaded class.                              */
+                               /* We have to do _eager_ resolving here. While the
+                                  class of the exception object is guaranteed to be
+                                  loaded, it may well have been loaded by a different
+                                  loader than the defining loader of m's class, which
+                                  is the one we must use to resolve the catch
+                                  class. Thus lazy resolving might fail, even if the
+                                  result of the resolution would be an already loaded
+                                  class. */
 
                                c = resolve_classref_eager(cr.ref);
 
@@ -1822,12 +1817,13 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
                                        goto exceptions_handle_exception_return;
                                }
 
-                               /* Ok, we resolved it. Enter it in the table, so we don't */
-                               /* have to do this again.                                 */
-                               /* XXX this write should be atomic. Is it?                */
+                               /* Ok, we resolved it. Enter it in the table, so we
+                                  don't have to do this again. */
+                               /* XXX this write should be atomic. Is it? */
 
-                               ex->catchtype.cls = c;
-                       } else {
+                               ete->catchtype.cls = c;
+                       }
+                       else {
                                c = cr.cls;
 
                                /* XXX I don't think this case can ever happen. -Edwin */
@@ -1837,9 +1833,9 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
                                                                                                         m->class->classloader))
                                                goto exceptions_handle_exception_return;
 
-                               /* XXX I think, if it is not linked, we can be sure that     */
-                               /* the exception object is no (indirect) instance of it, no? */
-                               /* -Edwin                                                    */
+                               /* XXX I think, if it is not linked, we can be sure
+                                  that the exception object is no (indirect) instance
+                                  of it, no?  -Edwin  */
                                if (!(c->state & CLASS_LINKED))
                                        if (!link_class(c))
                                                goto exceptions_handle_exception_return;
@@ -1857,32 +1853,28 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp)
 
                                if (opt_TraceExceptions) {
                                        exceptions_print_exception(xptr);
-                                       stacktrace_print_trace(xptr);
+                                       stacktrace_print_exception(xptr);
                                }
 #endif
 
-                               result = ex->handlerpc;
+                               result = ete->handlerpc;
                                goto exceptions_handle_exception_return;
                        }
                }
        }
+       }
 
 #if defined(ENABLE_THREADS)
-       /* is this method synchronized? */
+       /* Is this method realization synchronized? */
 
-       if (issync) {
-               /* get synchronization object */
+       if (code_is_synchronized(code)) {
+               /* Get synchronization object. */
 
-# if (defined(__MIPS__) && (SIZEOF_VOID_P == 4)) || defined(__I386__) || defined(__S390__) || defined(__POWERPC__)
-               /* XXX change this if we ever want to use 4-byte stackslots */
-               o = *((java_object_t **) (sp + issync - 8));
-# else
-               o = *((java_object_t **) (sp + issync - SIZEOF_VOID_P));
-# endif
+               o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
 
                assert(o != NULL);
 
-               lock_monitor_exit(o);
+               lock_monitor_exit(LLNI_QUICKWRAP(o));
        }
 #endif
 
@@ -2021,63 +2013,100 @@ void exceptions_print_current_exception(void)
 
 void exceptions_print_stacktrace(void)
 {
-       java_handle_t *oxptr;
-       java_handle_t *xptr;
-       classinfo     *c;
-       methodinfo    *m;
+       java_handle_t    *e;
+       java_handle_t    *ne;
+       classinfo        *c;
+       methodinfo       *m;
+
+#if defined(ENABLE_THREADS)
+       threadobject     *t;
+       java_lang_Thread *to;
+#endif
+
+       /* Get and clear exception because we are calling Java code
+          again. */
 
-       /* get original exception */
+       e = exceptions_get_and_clear_exception();
 
-       oxptr = exceptions_get_and_clear_exception();
+       if (e == NULL)
+               return;
 
-       if (oxptr == NULL)
-               vm_abort("exceptions_print_stacktrace: no exception thrown");
+#if 0
+       /* FIXME Enable me. */
+       if (builtin_instanceof(e, class_java_lang_ThreadDeath)) {
+               /* Don't print anything if we are being killed. */
+       }
+       else
+#endif
+       {
+               /* Get the exception class. */
 
-       /* clear exception, because we are calling jit code again */
+               LLNI_class_get(e, c);
 
-       LLNI_class_get(oxptr, c);
+               /* Find the printStackTrace() method. */
 
-       /* find the printStackTrace() method */
+               m = class_resolveclassmethod(c,
+                                                                        utf_printStackTrace,
+                                                                        utf_void__void,
+                                                                        class_java_lang_Object,
+                                                                        false);
 
-       m = class_resolveclassmethod(c,
-                                                                utf_printStackTrace,
-                                                                utf_void__void,
-                                                                class_java_lang_Object,
-                                                                false);
+               if (m == NULL)
+                       vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
 
-       if (m == NULL)
-               vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+               /* Print message. */
+
+               fprintf(stderr, "Exception ");
+
+#if defined(ENABLE_THREADS)
+               /* Print thread name.  We get the thread here explicitly as we
+                  need it afterwards. */
 
-       /* print compatibility message */
+               t  = thread_get_current();
+               to = (java_lang_Thread *) thread_get_object(t);
 
-       fprintf(stderr, "Exception in thread \"main\" ");
+               if (to != NULL) {
+                       fprintf(stderr, "in thread \"");
+                       thread_fprint_name(t, stderr);
+                       fprintf(stderr, "\" ");
+               }
+#endif
 
-       /* print the stacktrace */
+               /* Print the stacktrace. */
 
-       (void) vm_call_method(m, oxptr);
+               if (builtin_instanceof(e, class_java_lang_Throwable)) {
+                       (void) vm_call_method(m, e);
 
-       /* This normally means, we are EXTREMLY out of memory or
-          have a serious problem while printStackTrace. But may
-          be another exception, so print it. */
+                       /* If this happens we are EXTREMLY out of memory or have a
+                          serious problem while printStackTrace.  But may be
+                          another exception, so print it. */
 
-       xptr = exceptions_get_exception();
+                       ne = exceptions_get_exception();
 
-       if (xptr != NULL) {
-               fprintf(stderr, "Exception while printStackTrace(): ");
+                       if (ne != NULL) {
+                               fprintf(stderr, "Exception while printStackTrace(): ");
 
-               /* now print original exception */
+                               /* Print the current exception. */
 
-               exceptions_print_exception(xptr);
-               stacktrace_print_trace(xptr);
+                               exceptions_print_exception(ne);
+                               stacktrace_print_exception(ne);
 
-               /* now print original exception */
+                               /* Now print the original exception. */
 
-               fprintf(stderr, "Original exception was: ");
-               exceptions_print_exception(oxptr);
-               stacktrace_print_trace(oxptr);
-       }
+                               fprintf(stderr, "Original exception was: ");
+                               exceptions_print_exception(e);
+                               stacktrace_print_exception(e);
+                       }
+               }
+               else {
+                       fprintf(stderr, ". Uncaught exception of type ");
+                       /* FIXME This prints to stdout. */
+                       class_print(c);
+                       fprintf(stderr, ".");
+               }
 
-       fflush(stderr);
+               fflush(stderr);
+       }
 }