* src/vm/jit/sparc64/solaris/md-os.c: Implemented hardware exception handling.
[cacao.git] / src / vm / exceptions.c
index 24fb984ebdaeb62149667043537b14e5972dc3bd..51cb6ce9596ca00c6e37c28c310565768b3c0598 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: exceptions.c 7246 2007-01-29 18:49:05Z twisti $
+   $Id: exceptions.c 8178 2007-07-05 11:13:20Z michi $
 
 */
 
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
 
 #include "vm/types.h"
 
+#include "md-abi.h"
+
 #include "mm/memory.h"
 
 #include "native/jni.h"
 #include "native/native.h"
+
 #include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
 
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#else
-# include "threads/none/threads.h"
-#endif
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
 
 #include "toolbox/logging.h"
 #include "toolbox/util.h"
 #include "vm/vm.h"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/stacktrace.h"
 
 #include "vmcore/class.h"
 #include "vmcore/loader.h"
+#include "vmcore/method.h"
 #include "vmcore/options.h"
 
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
 
 /* for raising exceptions from native methods *********************************/
 
@@ -82,6 +92,25 @@ java_objectheader *_no_threads_exceptionptr = NULL;
 
 bool exceptions_init(void)
 {
+#if !(defined(__ARM__) && defined(__LINUX__))
+       /* On arm-linux the first memory page can't be mmap'ed, as it
+          contains the exception vectors. */
+
+       int pagesize;
+
+       /* mmap a memory page at address 0x0, so our hardware-exceptions
+          work. */
+
+       pagesize = getpagesize();
+
+       (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+#endif
+
+       /* check if we get into trouble with our hardware-exceptions */
+
+       if (OFFSET(java_bytearray, data) <= EXCEPTION_HARDWARE_LARGEST)
+               vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray, data), EXCEPTION_HARDWARE_LARGEST);
+
        /* java/lang/Throwable */
 
        if (!(class_java_lang_Throwable =
@@ -168,134 +197,68 @@ bool exceptions_init(void)
 }
 
 
-static void throw_exception_exit_intern(bool doexit)
-{
-       java_objectheader *xptr;
-       classinfo *c;
-       methodinfo *pss;
-
-       xptr = *exceptionptr;
-
-       if (xptr) {
-               /* clear exception, because we are calling jit code again */
-               *exceptionptr = NULL;
-
-               c = xptr->vftbl->class;
-
-               pss = class_resolveclassmethod(c,
-                                                                          utf_printStackTrace,
-                                                                          utf_void__void,
-                                                                          class_java_lang_Object,
-                                                                          false);
-
-               /* print the stacktrace */
-
-               if (pss) {
-                       (void) vm_call_method(pss, xptr);
-
-                       /* 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 (*exceptionptr) {
-                               java_lang_Throwable *t;
-
-                               t = (java_lang_Throwable *) *exceptionptr;
+/* exceptions_get_exception ****************************************************
 
-                               fprintf(stderr, "Exception while printStackTrace(): ");
-                               utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
+   Returns the current exception pointer of the current thread.
 
-                               if (t->detailMessage) {
-                                       char *buf;
+*******************************************************************************/
 
-                                       buf = javastring_tochar((java_objectheader *) t->detailMessage);
-                                       fprintf(stderr, ": %s", buf);
-                                       MFREE(buf, char, strlen(buf));
-                               }
-                                       
-                               fprintf(stderr, "\n");
-                       }
+java_objectheader *exceptions_get_exception(void)
+{
+       /* return the exception */
 
-               } else {
-                       utf_fprint_printable_ascii_classname(stderr, c->name);
-                       fprintf(stderr, ": printStackTrace()V not found!\n");
-               }
+       return *exceptionptr;
+}
 
-               fflush(stderr);
 
-               /* good bye! */
+/* exceptions_set_exception ****************************************************
 
-               if (doexit)
-                       exit(1);
-       }
-}
+   Sets the exception pointer of the current thread.
 
+*******************************************************************************/
 
-void throw_exception(void)
+void exceptions_set_exception(java_objectheader *o)
 {
-       throw_exception_exit_intern(false);
-}
-
+       /* set the exception */
 
-void throw_exception_exit(void)
-{
-       throw_exception_exit_intern(true);
+       *exceptionptr = o;
 }
 
 
-void throw_main_exception(void)
-{
-       fprintf(stderr, "Exception in thread \"main\" ");
-       fflush(stderr);
+/* exceptions_clear_exception **************************************************
 
-       throw_exception_exit_intern(false);
-}
+   Clears the current exception pointer of the current thread.
 
+*******************************************************************************/
 
-void throw_main_exception_exit(void)
+void exceptions_clear_exception(void)
 {
-       fprintf(stderr, "Exception in thread \"main\" ");
-       fflush(stderr);
-
-       throw_exception_exit_intern(true);
+       exceptions_set_exception(NULL);
 }
 
 
-void throw_cacao_exception_exit(const char *exception, const char *message, ...)
-{
-       s4 i;
-       char *tmp;
-       s4 len;
-       va_list ap;
+/* exceptions_get_and_clear_exception ******************************************
 
-       len = strlen(exception);
-       tmp = MNEW(char, len + 1);
-       strncpy(tmp, exception, len);
-       tmp[len] = '\0';
+   Gets the exception pointer of the current thread and clears it.
+   This function may return NULL.
 
-       /* convert to classname */
+*******************************************************************************/
 
-       for (i = len - 1; i >= 0; i--)
-               if (tmp[i] == '/') tmp[i] = '.';
+java_objectheader *exceptions_get_and_clear_exception(void)
+{
+       java_objectheader *o;
 
-       fprintf(stderr, "Exception in thread \"main\" %s", tmp);
+       /* get the exception */
 
-       MFREE(tmp, char, len);
+       o = exceptions_get_exception();
 
-       if (strlen(message) > 0) {
-               fprintf(stderr, ": ");
+       /* and clear the exception */
 
-               va_start(ap, message);
-               vfprintf(stderr, message, ap);
-               va_end(ap);
-       }
+       exceptions_clear_exception();
 
-       fprintf(stderr, "\n");
-       fflush(stderr);
-
-       /* good bye! */
+       /* return the exception */
 
-       exit(1);
+       return o;
 }
 
 
@@ -315,7 +278,7 @@ static java_objectheader *exceptions_new_class(classinfo *c)
        o = native_new_and_init(c);
 
        if (o == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        return o;
 }
@@ -338,7 +301,7 @@ static java_objectheader *exceptions_new_utf(utf *classname)
        c = load_class_bootstrap(classname);
 
        if (c == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        o = exceptions_new_class(c);
 
@@ -365,7 +328,7 @@ static void exceptions_throw_class(classinfo *c)
        if (o == NULL)
                return;
 
-       *exceptionptr = o;
+       exceptions_set_exception(o);
 }
 
 
@@ -406,20 +369,148 @@ static void exceptions_throw_utf(utf *classname)
 static void exceptions_throw_utf_throwable(utf *classname,
                                                                                   java_objectheader *cause)
 {
-       java_objectheader *o;
+       classinfo           *c;
+       java_objectheader   *o;
+       methodinfo          *m;
+       java_lang_Throwable *object;
+
+       object = (java_lang_Throwable *) cause;
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return;
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return;
+
+       /* call initializer */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init,
+                                                                utf_java_lang_Throwable__void,
+                                                                NULL,
+                                                                true);
+                                                     
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, cause);
+
+       exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_utf_exception **********************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/Exception exception.
+
+   IN:
+      classname....class name in UTF-8
+         exception....the given Exception
+
+*******************************************************************************/
+
+static void exceptions_throw_utf_exception(utf *classname,
+                                                                                  java_objectheader *exception)
+{
        classinfo         *c;
-   
+       java_objectheader *o;
+       methodinfo        *m;
+
        c = load_class_bootstrap(classname);
 
        if (c == NULL)
                return;
 
-       o = native_new_and_init_throwable(c, cause);
+       /* create object */
 
+       o = builtin_new(c);
+       
        if (o == NULL)
                return;
 
-       *exceptionptr = o;
+       /* call initializer */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init,
+                                                                utf_java_lang_Exception__V,
+                                                                NULL,
+                                                                true);
+                                                     
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, exception);
+
+       exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_utf_cause **************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/Throwable exception with initCause.
+
+   IN:
+      classname....class name in UTF-8
+         cause........the given Throwable
+
+*******************************************************************************/
+
+static void exceptions_throw_utf_cause(utf *classname, java_objectheader *cause)
+{
+       classinfo           *c;
+       java_objectheader   *o;
+       methodinfo          *m;
+       java_lang_Throwable *object;
+
+       object = (java_lang_Throwable *) cause;
+
+       c = load_class_bootstrap(classname);
+
+       if (c == NULL)
+               return;
+
+       /* create object */
+
+       o = builtin_new(c);
+       
+       if (o == NULL)
+               return;
+
+       /* call initializer */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_init,
+                                                                utf_java_lang_String__void,
+                                                                NULL,
+                                                                true);
+                                                     
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, object->detailMessage);
+
+       /* call initCause */
+
+       m = class_resolveclassmethod(c,
+                                                                utf_initCause,
+                                                                utf_java_lang_Throwable__java_lang_Throwable,
+                                                                NULL,
+                                                                true);
+
+       if (m == NULL)
+               return;
+
+       (void) vm_call_method(m, o, cause);
+
+       exceptions_set_exception(o);
 }
 
 
@@ -447,12 +538,12 @@ static java_objectheader *exceptions_new_utf_javastring(utf *classname,
        c = load_class_bootstrap(classname);
 
        if (c == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        o = native_new_and_init_string(c, message);
 
        if (o == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        return o;
 }
@@ -476,12 +567,12 @@ static java_objectheader *exceptions_new_class_utf(classinfo *c, utf *message)
        s = javastring_new(message);
 
        if (s == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        o = native_new_and_init_string(c, s);
 
        if (o == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        return o;
 }
@@ -510,7 +601,7 @@ static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message)
        c = load_class_bootstrap(classname);
 
        if (c == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        o = exceptions_new_class_utf(c, message);
 
@@ -518,38 +609,6 @@ static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message)
 }
 
 
-/* new_exception_message *******************************************************
-
-   Creates an exception object with the given name and initalizes it
-   with the given char message.
-
-   IN:
-      classname....class name in UTF-8
-         message......message in UTF-8
-
-   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_objectheader *new_exception_message(const char *classname,
-                                                                                               const char *message)
-{
-       java_objectheader *o;
-       java_objectheader *s;
-
-       s = javastring_new_from_utf_string(message);
-
-       if (s == NULL)
-               return *exceptionptr;
-
-       o = exceptions_new_utf_javastring(classname, s);
-
-       return o;
-}
-
-
 /* exceptions_throw_class_utf **************************************************
 
    Creates an exception object of the given class, initalizes and
@@ -563,7 +622,11 @@ static java_objectheader *new_exception_message(const char *classname,
 
 static void exceptions_throw_class_utf(classinfo *c, utf *message)
 {
-       *exceptionptr = exceptions_new_class_utf(c, message);
+       java_objectheader *o;
+
+       o = exceptions_new_class_utf(c, message);
+
+       exceptions_set_exception(o);
 }
 
 
@@ -580,56 +643,46 @@ static void exceptions_throw_class_utf(classinfo *c, utf *message)
 
 static void exceptions_throw_utf_utf(utf *classname, utf *message)
 {
-       *exceptionptr = exceptions_new_utf_utf(classname, message);
-}
+       java_objectheader *o;
 
+       o = exceptions_new_utf_utf(classname, message);
 
-/* new_exception_int ***********************************************************
+       exceptions_set_exception(o);
+}
 
-   Creates an exception object with the given name and initalizes it
-   with the given int value.
 
-   IN:
-      classname....class name in UTF-8
-         i............the integer
+/* exceptions_new_abstractmethoderror ****************************************
 
-   RETURN VALUE:
-      an exception pointer (in any case -- either it is the newly created
-         exception, or an exception thrown while trying to create it).
+   Generates a java.lang.AbstractMethodError for the VM.
 
 *******************************************************************************/
 
-java_objectheader *new_exception_int(const char *classname, s4 i)
+java_objectheader *exceptions_new_abstractmethoderror(void)
 {
        java_objectheader *o;
-       classinfo         *c;
-   
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
 
-       o = native_new_and_init_int(c, i);
-
-       if (!o)
-               return *exceptionptr;
+       o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
 
        return o;
 }
 
 
-/* exceptions_new_abstractmethoderror ****************************************
+/* exceptions_new_error ********************************************************
 
-   Generates a java.lang.AbstractMethodError for the VM.
+   Generates a java.lang.Error for the VM.
 
 *******************************************************************************/
 
-java_objectheader *exceptions_new_abstractmethoderror(void)
+#if defined(ENABLE_JAVAME_CLDC1_1)
+static java_objectheader *exceptions_new_error(utf *message)
 {
        java_objectheader *o;
 
-       o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
+       o = exceptions_new_class_utf(class_java_lang_Error, message);
 
        return o;
 }
+#endif
 
 
 /* exceptions_asm_new_abstractmethoderror **************************************
@@ -653,9 +706,7 @@ java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
 #if defined(ENABLE_JAVASE)
        e = exceptions_new_abstractmethoderror();
 #else
-       /* in the meantime we do this */
-
-       e = exceptions_new_virtualmachineerror();
+       e = exceptions_new_error(utf_java_lang_AbstractMethodError);
 #endif
 
        /* remove the stackframeinfo */
@@ -700,36 +751,13 @@ void exceptions_throw_abstractmethoderror(void)
    classloader.
 
    IN:
-      c............the class in which the error was found
+      c....the class in which the error was found
 
 *******************************************************************************/
 
 void exceptions_throw_classcircularityerror(classinfo *c)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
-
-       /* calculate message length */
-
-       msglen = utf_bytes(c->name) + strlen("0");
-
-       /* allocate a buffer */
-
-       msg = MNEW(char, msglen);
-
-       /* print message into allocated buffer */
-
-       utf_copy_classname(msg, c->name);
-
-       o = new_exception_message(utf_java_lang_ClassCircularityError, msg);
-
-       MFREE(msg, char, msglen);
-
-       if (o == NULL)
-               return;
-
-       *exceptionptr = o;
+       exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
 }
 
 
@@ -745,10 +773,10 @@ void exceptions_throw_classcircularityerror(classinfo *c)
 
 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
-       va_list            ap;
+       char    *msg;
+       s4       msglen;
+       va_list  ap;
+       utf     *u;
 
        /* calculate message length */
 
@@ -784,11 +812,15 @@ void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
        if (c != NULL)
                strcat(msg, ")");
 
-       o = new_exception_message(utf_java_lang_ClassFormatError, msg);
+       u = utf_new_char(msg);
+
+       /* free memory */
 
        MFREE(msg, char, msglen);
 
-       *exceptionptr = o;
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
 }
 
 
@@ -821,51 +853,57 @@ void exceptions_throw_classnotfoundexception(utf *name)
 
 void exceptions_throw_noclassdeffounderror(utf *name)
 {
+       if (vm_initializing)
+               vm_abort("java.lang.NoClassDefFoundError: %s", name->text);
+
        exceptions_throw_class_utf(class_java_lang_NoClassDefFoundError, name);
 }
 
 
-/* classnotfoundexception_to_noclassdeffounderror ******************************
+/* exceptions_throw_noclassdeffounderror_cause *********************************
 
-   Check the *exceptionptr for a ClassNotFoundException. If it is one,
-   convert it to a NoClassDefFoundError.
+   Generates and throws a java.lang.NoClassDefFoundError with the
+   given cause.
 
 *******************************************************************************/
 
-void classnotfoundexception_to_noclassdeffounderror(void)
+void exceptions_throw_noclassdeffounderror_cause(java_objectheader *cause)
 {
-       java_objectheader   *xptr;
-       java_objectheader   *cause;
-       java_lang_Throwable *t;
-       java_lang_String    *s;
+       exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
+}
 
-       /* get the cause */
 
-       cause = *exceptionptr;
+/* exceptions_throw_noclassdeffounderror_wrong_name ****************************
 
-       /* convert ClassNotFoundException's to NoClassDefFoundError's */
+   Generates and throws a java.lang.NoClassDefFoundError with a
+   specific message:
 
-       if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
-               /* clear exception, because we are calling jit code again */
+   IN:
+      name.........name of the class not found as a utf *
 
-               *exceptionptr = NULL;
+*******************************************************************************/
 
-               /* create new error */
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
+{
+       char *msg;
+       s4    msglen;
+       utf  *u;
 
-               t = (java_lang_Throwable *) cause;
-               s = t->detailMessage;
+       msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
+               utf_bytes(name) + strlen(")") + strlen("0");
 
-               xptr = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError, s);
+       msg = MNEW(char, msglen);
 
-               /* we had an exception while creating the error */
+       utf_copy_classname(msg, c->name);
+       strcat(msg, " (wrong name: ");
+       utf_cat_classname(msg, name);
+       strcat(msg, ")");
 
-               if (*exceptionptr)
-                       return;
+       u = utf_new_char(msg);
 
-               /* set new exception */
+       MFREE(msg, char, msglen);
 
-               *exceptionptr = xptr;
-       }
+       exceptions_throw_noclassdeffounderror(u);
 }
 
 
@@ -898,9 +936,9 @@ void exceptions_throw_exceptionininitializererror(java_objectheader *cause)
 
 void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
+       char *msg;
+       s4    msglen;
+       utf  *u;
 
        /* calculate exception message length */
 
@@ -913,17 +951,15 @@ void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *mes
        utf_copy_classname(msg, c->name);
        strcat(msg, message);
 
-       o = native_new_and_init_string(utf_java_lang_IncompatibleClassChangeError,
-                                                                  javastring_new_from_utf_string(msg));
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       if (o == NULL)
-               return;
+       /* throw exception */
 
-       *exceptionptr = o;
+       exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
 }
 
 
@@ -950,10 +986,10 @@ void exceptions_throw_instantiationerror(classinfo *c)
 
 void exceptions_throw_internalerror(const char *message, ...)
 {
-       java_objectheader *o;
-       va_list            ap;
-       char              *msg;
-       s4                 msglen;
+       va_list  ap;
+       char    *msg;
+       s4       msglen;
+       utf     *u;
 
        /* calculate exception message length */
 
@@ -971,18 +1007,15 @@ void exceptions_throw_internalerror(const char *message, ...)
        vsprintf(msg, message, ap);
        va_end(ap);
 
-       /* create exception object */
-
-       o = new_exception_message(utf_java_lang_InternalError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       if (o == NULL)
-               return;
+       /* throw exception */
 
-       *exceptionptr = o;
+       exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
 }
 
 
@@ -1031,7 +1064,7 @@ void exceptions_throw_linkageerror(const char *message, classinfo *c)
        if (o == NULL)
                return;
 
-       *exceptionptr = o;
+       exceptions_set_exception(o);
 }
 
 
@@ -1116,7 +1149,11 @@ void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
 
        MFREE(msg, char, msglen);
 
+#if defined(ENABLE_JAVASE)
        exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
+#else
+       exceptions_throw_class_utf(class_java_lang_Error, u);
+#endif
 }
 
 
@@ -1144,7 +1181,11 @@ void exceptions_throw_outofmemoryerror(void)
 
 void exceptions_throw_unsatisfiedlinkerror(utf *name)
 {
+#if defined(ENABLE_JAVASE)
        exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
+#else
+       exceptions_throw_class_utf(class_java_lang_Error, name);
+#endif
 }
 
 
@@ -1161,9 +1202,9 @@ void exceptions_throw_unsatisfiedlinkerror(utf *name)
 
 void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
 {
-       java_objectheader *o;
-       char              *msg;
-    s4                 msglen;
+       char *msg;
+    s4    msglen;
+       utf  *u;
 
        /* calculate exception message length */
 
@@ -1182,18 +1223,15 @@ void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
        sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
                        ma, mi);
 
-       /* create exception object */
-
-       o = new_exception_message(utf_java_lang_UnsupportedClassVersionError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       if (o == NULL)
-               return;
+       /* throw exception */
 
-       *exceptionptr = o;
+       exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
 }
 
 
@@ -1209,10 +1247,10 @@ void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
 
 void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
 {
-       java_objectheader *o;
-       va_list            ap;
-       char              *msg;
-       s4                 msglen;
+       va_list  ap;
+       char    *msg;
+       s4       msglen;
+       utf     *u;
 
        /* calculate exception message length */
 
@@ -1249,15 +1287,15 @@ void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
        vsprintf(msg + strlen(msg), message, ap);
        va_end(ap);
 
-       /* create exception object */
-
-       o = new_exception_message(utf_java_lang_VerifyError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       *exceptionptr = o;
+       /* throw exception */
+
+       exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
 }
 
 
@@ -1275,18 +1313,18 @@ void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
 
 *******************************************************************************/
 
-void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
+void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
 {
-       java_objectheader *o;
-       char              *msg;
-       s4                 msglen;
-       char              *typename;
+       char *msg;
+       s4    msglen;
+       char *typename;
+       utf  *u;
 
        /* calculate exception message length */
 
        msglen = 0;
 
-       if (m)
+       if (m != NULL)
                msglen = strlen("(class: ") + utf_bytes(m->class->name) +
                        strlen(", method: ") + utf_bytes(m->name) +
                        strlen(" signature: ") + utf_bytes(m->descriptor) +
@@ -1299,7 +1337,7 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
 
        /* generate message */
 
-       if (m) {
+       if (m != NULL) {
                strcpy(msg, "(class: ");
                utf_cat_classname(msg, m->class->name);
                strcat(msg, ", method: ");
@@ -1312,7 +1350,8 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
                msg[0] = 0;
        }
 
-       strcat(msg,"Expecting to find ");
+       strcat(msg, "Expecting to find ");
+
        switch (type) {
                case TYPE_INT: typename = "integer"; break;
                case TYPE_LNG: typename = "long"; break;
@@ -1322,30 +1361,19 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
                case TYPE_RET: typename = "returnAddress"; break;
                default:       typename = "<INVALID>"; assert(0); break;
        }
+
        strcat(msg, typename);
        strcat(msg, " on stack");
 
-       /* create exception object */
-
-       o = new_exception_message(utf_java_lang_VerifyError, msg);
+       u = utf_new_char(msg);
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
-       *exceptionptr = o;
-}
-
+       /* throw exception */
 
-/* exceptions_throw_virtualmachineerror ****************************************
-
-   Generates and throws a java.lang.VirtualMachineError for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_virtualmachineerror(void)
-{
-       exceptions_throw_class(class_java_lang_VirtualMachineError);
+       exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
 }
 
 
@@ -1359,10 +1387,8 @@ java_objectheader *exceptions_new_arithmeticexception(void)
 {
        java_objectheader *o;
 
-       o = new_exception_message(utf_java_lang_ArithmeticException, "/ by zero");
-
-       if (o == NULL)
-               return *exceptionptr;
+       o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
+                                                          utf_division_by_zero);
 
        return o;
 }
@@ -1390,18 +1416,18 @@ java_objectheader *exceptions_new_arrayindexoutofboundsexception(s4 index)
                                                                 true);
 
        if (m == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        s = vm_call_method(m, NULL, index);
 
        if (s == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
                                                                          s);
 
        if (o == NULL)
-               return *exceptionptr;
+               return exceptions_get_exception();
 
        return o;
 }
@@ -1443,16 +1469,10 @@ java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
 {
        java_objectheader *e;
        utf               *classname;
-       java_lang_String  *s;
 
        classname = o->vftbl->class->name;
 
-       s = javastring_new(classname);
-
-       e = native_new_and_init_string(class_java_lang_ClassCastException, s);
-
-       if (e == NULL)
-               return *exceptionptr;
+       e = exceptions_new_class_utf(class_java_lang_ClassCastException, classname);
 
        return e;
 }
@@ -1477,11 +1497,9 @@ void exceptions_throw_clonenotsupportedexception(void)
 
 *******************************************************************************/
 
-void exceptions_throw_illegalaccessexception(classinfo *c)
+void exceptions_throw_illegalaccessexception(utf *message)
 {
-       /* XXX handle argument */
-
-       exceptions_throw_utf(utf_java_lang_IllegalAccessException);
+       exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
 }
 
 
@@ -1537,8 +1555,8 @@ void exceptions_throw_interruptedexception(void)
 
 /* exceptions_throw_invocationtargetexception **********************************
 
-   Generates and throws a java.lang.InvocationTargetException for the
-   VM.
+   Generates and throws a java.lang.reflect.InvocationTargetException
+   for the VM.
 
    IN:
       cause......cause exception object
@@ -1547,7 +1565,7 @@ void exceptions_throw_interruptedexception(void)
 
 void exceptions_throw_invocationtargetexception(java_objectheader *cause)
 {
-       exceptions_throw_utf_throwable(utf_java_lang_InvocationTargetException,
+       exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
                                                                   cause);
 }
 
@@ -1594,6 +1612,19 @@ void exceptions_throw_nullpointerexception(void)
 }
 
 
+/* exceptions_throw_privilegedactionexception **********************************
+
+   Generates and throws a java.security.PrivilegedActionException.
+
+*******************************************************************************/
+
+void exceptions_throw_privilegedactionexception(java_objectheader *exception)
+{
+       exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
+                                                                  exception);
+}
+
+
 /* exceptions_throw_stringindexoutofboundsexception ****************************
 
    Generates and throws a java.lang.StringIndexOutOfBoundsException
@@ -1607,73 +1638,169 @@ void exceptions_throw_stringindexoutofboundsexception(void)
 }
 
 
-/* exceptions_get_exception ****************************************************
+/* exceptions_classnotfoundexception_to_noclassdeffounderror *******************
 
-   Returns the current exception pointer of the current thread.
+   Check the exception for a ClassNotFoundException. If it is one,
+   convert it to a NoClassDefFoundError.
 
 *******************************************************************************/
 
-java_objectheader *exceptions_get_exception(void)
+void exceptions_classnotfoundexception_to_noclassdeffounderror(void)
 {
-       /* return the exception */
+       java_objectheader   *o;
+       java_objectheader   *cause;
+       java_lang_Throwable *object;
+       java_objectheader   *s;
 
-       return *exceptionptr;
-}
+       /* get the cause */
 
+       cause = exceptions_get_exception();
 
-/* exceptions_set_exception ****************************************************
+       /* convert ClassNotFoundException's to NoClassDefFoundError's */
 
-   Sets the exception pointer of the current thread.
+       if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
+               /* clear exception, because we are calling jit code again */
 
-*******************************************************************************/
+               exceptions_clear_exception();
 
-void exceptions_set_exception(java_objectheader *o)
-{
-       /* set the exception */
+               /* create new error */
 
-       *exceptionptr = o;
+               object = (java_lang_Throwable *) cause;
+               s      = (java_objectheader *) object->detailMessage;
+
+               o = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
+                                                                                 s);
+
+               /* we had an exception while creating the error */
+
+               if (exceptions_get_exception())
+                       return;
+
+               /* set new exception */
+
+               exceptions_set_exception(o);
+       }
 }
 
 
-/* exceptions_clear_exception **************************************************
+/* exceptions_fillinstacktrace *************************************************
 
-   Clears the current exception pointer of the current thread.
+   Calls the fillInStackTrace-method of the currently thrown
+   exception.
 
 *******************************************************************************/
 
-void exceptions_clear_exception(void)
+java_objectheader *exceptions_fillinstacktrace(void)
 {
-       /* and clear the exception */
+       java_objectheader *o;
+       methodinfo        *m;
+
+       /* get exception */
+
+       o = exceptions_get_and_clear_exception();
 
-       *exceptionptr = NULL;
+       assert(o);
+
+       /* 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 */
+
+       (void) vm_call_method(m, o);
+
+       /* return exception object */
+
+       return o;
 }
 
 
-/* exceptions_get_and_clear_exception ******************************************
+/* exceptions_new_hardware_exception *******************************************
 
-   Gets the exception pointer of the current thread and clears it.
-   This function may return NULL.
+   Creates the correct exception for a hardware-exception thrown and
+   caught by a signal handler.
 
 *******************************************************************************/
 
-java_objectheader *exceptions_get_and_clear_exception(void)
+java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val, stackframeinfo *sfi)
 {
-       java_objectheader **p;
-       java_objectheader  *e;
+       java_objectheader *e;
+       java_objectheader *o;
+       s4                 index;
 
-       /* get the pointer of the exception pointer */
+       /* create stackframeinfo */
 
-       p = exceptionptr;
+       stacktrace_create_extern_stackframeinfo(sfi, pv, sp, ra, xpc);
 
-       /* get the exception */
+       switch (type) {
+       case EXCEPTION_HARDWARE_NULLPOINTER:
+               e = exceptions_new_nullpointerexception();
+               break;
 
-       e = *p;
+       case EXCEPTION_HARDWARE_ARITHMETIC:
+               e = exceptions_new_arithmeticexception();
+               break;
 
-       /* and clear the exception */
+       case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
+               index = (s4) val;
+               e = exceptions_new_arrayindexoutofboundsexception(index);
+               break;
 
-       *p = NULL;
+       case EXCEPTION_HARDWARE_CLASSCAST:
+               o = (java_objectheader *) val;
+               e = exceptions_new_classcastexception(o);
+               break;
 
-       /* return the exception */
+       case EXCEPTION_HARDWARE_EXCEPTION:
+               e = exceptions_fillinstacktrace();
+               break;
+
+       case EXCEPTION_HARDWARE_PATCHER:
+               e = patcher_handler(xpc);
+               break;
+
+       default:
+               /* let's try to get a backtrace */
+
+               codegen_get_pv_from_pc(xpc);
+
+               /* if that does not work, print more debug info */
+
+               log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
+
+#if SIZEOF_VOID_P == 8
+               log_println("PC=0x%016lx", xpc);
+#else
+               log_println("PC=0x%08x", xpc);
+#endif
+
+#if defined(ENABLE_DISASSEMBLER)
+               log_println("machine instruction at PC:");
+               disassinstr(xpc);
+#endif
+
+               vm_abort("Exiting...");
+
+               /* keep compiler happy */
+
+               e = NULL;
+       }
+
+       /* remove stackframeinfo */
+
+       stacktrace_remove_stackframeinfo(sfi);
+
+       /* return the exception object */
 
        return e;
 }
@@ -1712,6 +1839,15 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
        java_objectheader     *o;
 #endif
 
+#ifdef __S390__
+       /* Addresses are 31 bit integers */
+#      define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF)
+#else
+#      define ADDR_MASK(x) (x)
+#endif
+
+       xpc = ADDR_MASK(xpc);
+
        /* get info from the method header */
 
        code                 = *((codeinfo **)            (pv + CodeinfoPointer));
@@ -1727,10 +1863,14 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 #if !defined(NDEBUG)
        /* print exception trace */
 
-       if (opt_verbose || opt_verbosecall || opt_verboseexception)
+       if (opt_verbose || opt_verbosecall || opt_TraceExceptions)
                builtin_trace_exception(xptr, m, xpc, 1);
 #endif
 
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_throw(xptr);
+#endif
+
        for (i = 0; i < exceptiontablelength; i++) {
                /* ATTENTION: keep this here, as we need to decrement the
            pointer before the loop executes! */
@@ -1746,7 +1886,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                /* is the xpc is the current catch range */
 
-               if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
+               if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) {
                        cr = ex->catchtype;
 
                        /* NULL catches everything */
@@ -1755,7 +1895,11 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 #if !defined(NDEBUG)
                                /* Print stacktrace of exception when caught. */
 
-                               if (opt_verboseexception) {
+#if defined(ENABLE_VMLOG)
+                               vmlog_cacao_catch(xptr);
+#endif
+
+                               if (opt_TraceExceptions) {
                                        exceptions_print_exception(xptr);
                                        stacktrace_print_trace(xptr);
                                }
@@ -1812,7 +1956,11 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 #if !defined(NDEBUG)
                                /* Print stacktrace of exception when caught. */
 
-                               if (opt_verboseexception) {
+#if defined(ENABLE_VMLOG)
+                               vmlog_cacao_catch(xptr);
+#endif
+
+                               if (opt_TraceExceptions) {
                                        exceptions_print_exception(xptr);
                                        stacktrace_print_trace(xptr);
                                }
@@ -1844,6 +1992,10 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
        /* none of the exceptions catch this one */
 
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_unwnd_method(m);
+#endif
+
        return NULL;
 }
 #endif /* defined(ENABLE_JIT) */
@@ -1880,7 +2032,7 @@ void exceptions_print_exception(java_objectheader *xptr)
        utf_display_printable_ascii_classname(t->header.vftbl->class->name);
 
        if (t->detailMessage != NULL) {
-               u = javastring_toutf(t->detailMessage, false);
+               u = javastring_toutf((java_objectheader *) t->detailMessage, false);
 
                printf(": ");
                utf_display_printable_ascii(u);
@@ -1895,8 +2047,9 @@ void exceptions_print_exception(java_objectheader *xptr)
                printf("Caused by: ");
                utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
 
-               if (cause->detailMessage) {
-                       u = javastring_toutf(cause->detailMessage, false);
+               if (cause->detailMessage != NULL) {
+                       u = javastring_toutf((java_objectheader *) cause->detailMessage,
+                                                                false);
 
                        printf(": ");
                        utf_display_printable_ascii(u);
@@ -1917,11 +2070,83 @@ void exceptions_print_exception(java_objectheader *xptr)
 
 void exceptions_print_current_exception(void)
 {
+       java_objectheader *o;
+
+       o = exceptions_get_exception();
+
+       exceptions_print_exception(o);
+}
+
+
+/* exceptions_print_stacktrace *************************************************
+
+   Prints a pending exception with Throwable.printStackTrace().  If
+   there happens an exception during printStackTrace(), we print the
+   thrown exception and the original one.
+
+   NOTE: This function calls Java code.
+
+*******************************************************************************/
+
+void exceptions_print_stacktrace(void)
+{
+       java_objectheader *oxptr;
        java_objectheader *xptr;
+       classinfo         *c;
+       methodinfo        *m;
+
+       /* get original exception */
+
+       oxptr = exceptions_get_and_clear_exception();
+
+       if (oxptr == NULL)
+               vm_abort("exceptions_print_stacktrace: no exception thrown");
+
+       /* clear exception, because we are calling jit code again */
+
+       c = oxptr->vftbl->class;
+
+       /* find the printStackTrace() method */
+
+       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");
+
+       /* print compatibility message */
+
+       fprintf(stderr, "Exception in thread \"main\" ");
+
+       /* print the stacktrace */
+
+       (void) vm_call_method(m, oxptr);
+
+       /* This normally means, we are EXTREMLY out of memory or
+          have a serious problem while printStackTrace. But may
+          be another exception, so print it. */
 
-       xptr = *exceptionptr;
+       xptr = exceptions_get_exception();
 
-       exceptions_print_exception(xptr);
+       if (xptr != NULL) {
+               fprintf(stderr, "Exception while printStackTrace(): ");
+
+               /* now print original exception */
+
+               exceptions_print_exception(xptr);
+               stacktrace_print_trace(xptr);
+
+               /* now print original exception */
+
+               fprintf(stderr, "Original exception was: ");
+               exceptions_print_exception(oxptr);
+               stacktrace_print_trace(oxptr);
+       }
+
+       fflush(stderr);
 }