* src/vm/jit/stack.c (GET_NEW_VAR): Fixed macro argument.
[cacao.git] / src / vm / exceptions.c
index cf2c5c7c34ee28908538a87938129689f41ac1a9..41d13867b97a67644e1bf7b9af1bc389debad132 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Edwin Steiner
 
 
    Changes: Edwin Steiner
 
-   $Id: exceptions.c 4552 2006-03-04 17:15:44Z twisti $
+   $Id: exceptions.c 5586 2006-09-29 14:21:42Z edwin $
 
 */
 
 
 */
 
@@ -62,7 +62,7 @@
 
 /* for raising exceptions from native methods *********************************/
 
 
 /* for raising exceptions from native methods *********************************/
 
-#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
+#if !defined(ENABLE_THREADS)
 java_objectheader *_no_threads_exceptionptr = NULL;
 #endif
 
 java_objectheader *_no_threads_exceptionptr = NULL;
 #endif
 
@@ -97,11 +97,11 @@ bool exceptions_init(void)
                !link_class(class_java_lang_Error))
                return false;
 
                !link_class(class_java_lang_Error))
                return false;
 
-       /* java/lang/NoClassDefFoundError */
+       /* java/lang/AbstractMethodError */
 
 
-       if (!(class_java_lang_NoClassDefFoundError =
-                 load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
-               !link_class(class_java_lang_NoClassDefFoundError))
+       if (!(class_java_lang_AbstractMethodError =
+                 load_class_bootstrap(utf_java_lang_AbstractMethodError)) ||
+               !link_class(class_java_lang_AbstractMethodError))
                return false;
 
        /* java/lang/LinkageError */
                return false;
 
        /* java/lang/LinkageError */
@@ -111,6 +111,13 @@ bool exceptions_init(void)
                !link_class(class_java_lang_LinkageError))
                return false;
 
                !link_class(class_java_lang_LinkageError))
                return false;
 
+       /* java/lang/NoClassDefFoundError */
+
+       if (!(class_java_lang_NoClassDefFoundError =
+                 load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
+               !link_class(class_java_lang_NoClassDefFoundError))
+               return false;
+
        /* java/lang/NoSuchMethodError */
 
        if (!(class_java_lang_NoSuchMethodError =
        /* java/lang/NoSuchMethodError */
 
        if (!(class_java_lang_NoSuchMethodError =
@@ -133,6 +140,13 @@ bool exceptions_init(void)
                !link_class(class_java_lang_Exception))
                return false;
 
                !link_class(class_java_lang_Exception))
                return false;
 
+       /* java/lang/ClassCastException */
+
+       if (!(class_java_lang_ClassCastException =
+                 load_class_bootstrap(utf_java_lang_ClassCastException)) ||
+               !link_class(class_java_lang_ClassCastException))
+               return false;
+
        /* java/lang/ClassNotFoundException */
 
        if (!(class_java_lang_ClassNotFoundException =
        /* java/lang/ClassNotFoundException */
 
        if (!(class_java_lang_ClassNotFoundException =
@@ -189,7 +203,7 @@ static void throw_exception_exit_intern(bool doexit)
                /* print the stacktrace */
 
                if (pss) {
                /* print the stacktrace */
 
                if (pss) {
-                       (void) vm_call_method_intern(pss, xptr, NULL, NULL, NULL);
+                       (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      */
 
                        /* This normally means, we are EXTREMLY out of memory or have a   */
                        /* serious problem while printStackTrace. But may be another      */
@@ -201,7 +215,7 @@ static void throw_exception_exit_intern(bool doexit)
                                t = (java_lang_Throwable *) *exceptionptr;
 
                                fprintf(stderr, "Exception while printStackTrace(): ");
                                t = (java_lang_Throwable *) *exceptionptr;
 
                                fprintf(stderr, "Exception while printStackTrace(): ");
-                               utf_fprint_classname(stderr, t->header.vftbl->class->name);
+                               utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
 
                                if (t->detailMessage) {
                                        char *buf;
 
                                if (t->detailMessage) {
                                        char *buf;
@@ -215,7 +229,7 @@ static void throw_exception_exit_intern(bool doexit)
                        }
 
                } else {
                        }
 
                } else {
-                       utf_fprint_classname(stderr, c->name);
+                       utf_fprint_printable_ascii_classname(stderr, c->name);
                        fprintf(stderr, ": printStackTrace()V not found!\n");
                }
 
                        fprintf(stderr, ": printStackTrace()V not found!\n");
                }
 
@@ -314,6 +328,13 @@ void exceptions_throw_outofmemory_exit(void)
 
    Creates an exception object with the given name and initalizes it.
 
 
    Creates an exception object with the given name and initalizes it.
 
+   IN:
+      classname....class name 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).
+
 *******************************************************************************/
 
 java_objectheader *new_exception(const char *classname)
 *******************************************************************************/
 
 java_objectheader *new_exception(const char *classname)
@@ -338,23 +359,26 @@ java_objectheader *new_exception(const char *classname)
    Creates an exception object with the given name and initalizes it
    with the given char 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).
+
 *******************************************************************************/
 
 java_objectheader *new_exception_message(const char *classname,
                                                                                 const char *message)
 {
 *******************************************************************************/
 
 java_objectheader *new_exception_message(const char *classname,
                                                                                 const char *message)
 {
-       java_objectheader *o;
-       classinfo         *c;
-   
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
+       java_lang_String *s;
 
 
-       o = native_new_and_init_string(c, javastring_new_char(message));
-
-       if (!o)
+       s = javastring_new_from_utf_string(message);
+       if (!s)
                return *exceptionptr;
 
                return *exceptionptr;
 
-       return o;
+       return new_exception_javastring(classname, s);
 }
 
 
 }
 
 
@@ -363,6 +387,14 @@ java_objectheader *new_exception_message(const char *classname,
    Creates an exception object with the given name and initalizes it
    with the given java/lang/Throwable exception.
 
    Creates an exception object with the given name and initalizes it
    with the given java/lang/Throwable exception.
 
+   IN:
+      classname....class name in UTF-8
+         throwable....the given Throwable
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
+
 *******************************************************************************/
 
 java_objectheader *new_exception_throwable(const char *classname,
 *******************************************************************************/
 
 java_objectheader *new_exception_throwable(const char *classname,
@@ -388,22 +420,25 @@ java_objectheader *new_exception_throwable(const char *classname,
    Creates an exception object with the given name and initalizes it
    with the given utf message.
 
    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).
+
 *******************************************************************************/
 
 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
 {
 *******************************************************************************/
 
 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
 {
-       java_objectheader *o;
-       classinfo         *c;
-   
-       if (!(c = load_class_bootstrap(utf_new_char(classname))))
-               return *exceptionptr;
-
-       o = native_new_and_init_string(c, javastring_new(message));
+       java_lang_String *s;
 
 
-       if (!o)
+       s = javastring_new(message);
+       if (!s)
                return *exceptionptr;
 
                return *exceptionptr;
 
-       return o;
+       return new_exception_javastring(classname, s);
 }
 
 
 }
 
 
@@ -412,6 +447,14 @@ java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
    Creates an exception object with the given name and initalizes it
    with the given java/lang/String message.
 
    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).
+
 *******************************************************************************/
 
 java_objectheader *new_exception_javastring(const char *classname,
 *******************************************************************************/
 
 java_objectheader *new_exception_javastring(const char *classname,
@@ -437,6 +480,14 @@ java_objectheader *new_exception_javastring(const char *classname,
    Creates an exception object with the given name and initalizes it
    with the given int value.
 
    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
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
+
 *******************************************************************************/
 
 java_objectheader *new_exception_int(const char *classname, s4 i)
 *******************************************************************************/
 
 java_objectheader *new_exception_int(const char *classname, s4 i)
@@ -456,10 +507,77 @@ java_objectheader *new_exception_int(const char *classname, s4 i)
 }
 
 
 }
 
 
+/* exceptions_new_abstractmethoderror ******************************************
+
+   Generates a java.lang.AbstractMethodError for the VM.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_abstractmethoderror(void)
+{
+       java_objectheader *e;
+
+       e = native_new_and_init(class_java_lang_AbstractMethodError);
+
+       if (e == NULL)
+               return *exceptionptr;
+
+       return e;
+}
+
+
+/* exceptions_asm_new_abstractmethoderror **************************************
+
+   Generates a java.lang.AbstractMethodError for
+   asm_abstractmethoderror.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
+{
+       stackframeinfo     sfi;
+       java_objectheader *e;
+
+       /* create the stackframeinfo (XPC is equal to RA) */
+
+       stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
+
+       /* create the exception */
+
+       e = exceptions_new_abstractmethoderror();
+
+       /* remove the stackframeinfo */
+
+       stacktrace_remove_stackframeinfo(&sfi);
+
+       return e;
+}
+
+
+/* exceptions_throw_abstractmethoderror ****************************************
+
+   Generates a java.lang.AbstractMethodError for the VM and throws it.
+
+*******************************************************************************/
+
+void exceptions_throw_abstractmethoderror(void)
+{
+       *exceptionptr = exceptions_new_abstractmethoderror();
+}
+
+
 /* new_classformaterror ********************************************************
 
    generates a java.lang.ClassFormatError for the classloader
 
 /* new_classformaterror ********************************************************
 
    generates a java.lang.ClassFormatError for the classloader
 
+   IN:
+      c............the class in which the error was found
+         message......UTF-8 format 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).
+
 *******************************************************************************/
 
 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 *******************************************************************************/
 
 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
@@ -474,7 +592,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
        msglen = 0;
 
        if (c)
        msglen = 0;
 
        if (c)
-               msglen += utf_strlen(c->name) + strlen(" (");
+               msglen += utf_bytes(c->name) + strlen(" (");
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
@@ -492,7 +610,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
        /* print message into allocated buffer */
 
        if (c) {
        /* print message into allocated buffer */
 
        if (c) {
-               utf_sprint_classname(msg, c->name);
+               utf_copy_classname(msg, c->name);
                strcat(msg, " (");
        }
 
                strcat(msg, " (");
        }
 
@@ -513,8 +631,15 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 
 /* exceptions_throw_classformaterror *******************************************
 
 
 /* exceptions_throw_classformaterror *******************************************
 
-   Generates a java.lang.ClassFormatError for the VM system throw it
-   in the VM system.
+   Generate a java.lang.ClassFormatError for the VM system and throw it.
+
+   IN:
+      c............the class in which the error was found
+         message......UTF-8 format 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).
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
@@ -532,14 +657,25 @@ void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
 
    Generates a java.lang.ClassNotFoundException for the classloader.
 
 
    Generates a java.lang.ClassNotFoundException for the classloader.
 
+   IN:
+      name.........name of the class not found as a 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).
+
 *******************************************************************************/
 
 java_objectheader *new_classnotfoundexception(utf *name)
 {
        java_objectheader *o;
 *******************************************************************************/
 
 java_objectheader *new_classnotfoundexception(utf *name)
 {
        java_objectheader *o;
+       java_lang_String  *s;
 
 
-       o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
-                                                                  javastring_new(name));
+       s = javastring_new(name);
+       if (!s)
+               return *exceptionptr;
+
+       o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s);
 
        if (!o)
                return *exceptionptr;
 
        if (!o)
                return *exceptionptr;
@@ -552,14 +688,25 @@ java_objectheader *new_classnotfoundexception(utf *name)
 
    Generates a java.lang.NoClassDefFoundError
 
 
    Generates a java.lang.NoClassDefFoundError
 
+   IN:
+      name.........name of the class not found as a 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).
+
 *******************************************************************************/
 
 java_objectheader *new_noclassdeffounderror(utf *name)
 {
        java_objectheader *o;
 *******************************************************************************/
 
 java_objectheader *new_noclassdeffounderror(utf *name)
 {
        java_objectheader *o;
+       java_lang_String  *s;
+
+       s = javastring_new(name);
+       if (!s)
+               return *exceptionptr;
 
 
-       o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
-                                                                  javastring_new(name));
+       o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s);
 
        if (!o)
                return *exceptionptr;
 
        if (!o)
                return *exceptionptr;
@@ -613,6 +760,13 @@ void classnotfoundexception_to_noclassdeffounderror(void)
 
    Generates a java.lang.InternalError for the VM.
 
 
    Generates a java.lang.InternalError for the VM.
 
+   IN:
+      message......UTF-8 message format 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).
+
 *******************************************************************************/
 
 java_objectheader *new_internalerror(const char *message, ...)
 *******************************************************************************/
 
 java_objectheader *new_internalerror(const char *message, ...)
@@ -653,7 +807,15 @@ java_objectheader *new_internalerror(const char *message, ...)
 /* exceptions_new_linkageerror *************************************************
 
    Generates a java.lang.LinkageError with an error message.
 /* exceptions_new_linkageerror *************************************************
 
    Generates a java.lang.LinkageError with an error message.
-   If c != NULL, the name of c is appended to the error message.
+
+   IN:
+      message......UTF-8 message
+         c............class related to the error. If this is != NULL
+                      the name of c is appended to the error message.
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
@@ -668,7 +830,7 @@ java_objectheader *exceptions_new_linkageerror(const char *message,
 
        msglen = strlen(message) + 1;
        if (c) {
 
        msglen = strlen(message) + 1;
        if (c) {
-               msglen += utf_strlen(c->name);
+               msglen += utf_bytes(c->name);
        }
                
        /* allocate memory */
        }
                
        /* allocate memory */
@@ -679,16 +841,19 @@ java_objectheader *exceptions_new_linkageerror(const char *message,
 
        strcpy(msg,message);
        if (c) {
 
        strcpy(msg,message);
        if (c) {
-               utf_strcat(msg, c->name);
+               utf_cat_classname(msg, c->name);
        }
 
        o = native_new_and_init_string(class_java_lang_LinkageError,
        }
 
        o = native_new_and_init_string(class_java_lang_LinkageError,
-                                                                  javastring_new_char(msg));
+                                                                  javastring_new_from_utf_string(msg));
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
+       if (!o)
+               return *exceptionptr;
+
        return o;
 }
 
        return o;
 }
 
@@ -697,6 +862,15 @@ java_objectheader *exceptions_new_linkageerror(const char *message,
 
    Generates a java.lang.NoSuchMethodError with an error message.
 
 
    Generates a java.lang.NoSuchMethodError with an error message.
 
+   IN:
+      c............class in which the method was not found
+         name.........name of the method
+         desc.........descriptor of the method
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
+
 *******************************************************************************/
 
 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
 *******************************************************************************/
 
 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
@@ -708,8 +882,8 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
 
        /* calculate exception message length */
 
 
        /* calculate exception message length */
 
-       msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
-               utf_strlen(desc) + strlen("0");
+       msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
+               utf_bytes(desc) + strlen("0");
 
        /* allocate memory */
 
 
        /* allocate memory */
 
@@ -717,18 +891,21 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
 
        /* generate message */
 
 
        /* generate message */
 
-       utf_sprint(msg, c->name);
+       utf_copy_classname(msg, c->name);
        strcat(msg, ".");
        strcat(msg, ".");
-       utf_strcat(msg, name);
-       utf_strcat(msg, desc);
+       utf_cat(msg, name);
+       utf_cat(msg, desc);
 
        o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
 
        o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
-                                                                  javastring_new_char(msg));
+                                                                  javastring_new_from_utf_string(msg));
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
+       if (!o)
+               return *exceptionptr;
+
        return o;
 }
 
        return o;
 }
 
@@ -737,6 +914,11 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
 
    Generates a java.lang.NoSuchMethodError with an error message.
 
 
    Generates a java.lang.NoSuchMethodError with an error message.
 
+   IN:
+      c............class in which the method was not found
+         name.........name of the method
+         desc.........descriptor of the method
+
 *******************************************************************************/
 
 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
 *******************************************************************************/
 
 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
@@ -747,7 +929,15 @@ void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
 
 /* new_unsupportedclassversionerror ********************************************
 
 
 /* new_unsupportedclassversionerror ********************************************
 
-   generates a java.lang.UnsupportedClassVersionError for the classloader
+   Generate a java.lang.UnsupportedClassVersionError for the classloader
+
+   IN:
+      c............class in which the method was not found
+         message......UTF-8 format 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).
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
@@ -760,7 +950,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 
        /* calculate exception message length */
 
 
        /* calculate exception message length */
 
-       msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
+       msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0");
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
@@ -772,7 +962,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 
        /* generate message */
 
 
        /* generate message */
 
-       utf_sprint_classname(msg, c->name);
+       utf_copy_classname(msg, c->name);
        strcat(msg, " (");
 
        va_start(ap, message);
        strcat(msg, " (");
 
        va_start(ap, message);
@@ -794,13 +984,22 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 }
 
 
 }
 
 
-/* new_verifyerror *************************************************************
+/* exceptions_new_verifyerror **************************************************
+
+   Generates a java.lang.VerifyError for the JIT compiler.
 
 
-   generates a java.lang.VerifyError for the jit compiler
+   IN:
+      m............method in which the error was found
+         message......UTF-8 format 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).
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
+java_objectheader *exceptions_new_verifyerror(methodinfo *m,
+                                                                                         const char *message, ...)
 {
        java_objectheader *o;
        va_list            ap;
 {
        java_objectheader *o;
        va_list            ap;
@@ -814,9 +1013,9 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
        msglen = 0;
 
        if (m)
        msglen = 0;
 
        if (m)
-               msglen = strlen("(class: ") + utf_strlen(m->class->name) +
-                       strlen(", method: ") + utf_strlen(m->name) +
-                       strlen(" signature: ") + utf_strlen(m->descriptor) +
+               msglen = strlen("(class: ") + utf_bytes(m->class->name) +
+                       strlen(", method: ") + utf_bytes(m->name) +
+                       strlen(" signature: ") + utf_bytes(m->descriptor) +
                        strlen(") ") + strlen("0");
 
        va_start(ap, message);
                        strlen(") ") + strlen("0");
 
        va_start(ap, message);
@@ -831,11 +1030,11 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 
        if (m) {
                strcpy(msg, "(class: ");
 
        if (m) {
                strcpy(msg, "(class: ");
-               utf_strcat(msg, m->class->name);
+               utf_cat_classname(msg, m->class->name);
                strcat(msg, ", method: ");
                strcat(msg, ", method: ");
-               utf_strcat(msg, m->name);
+               utf_cat(msg, m->name);
                strcat(msg, " signature: ");
                strcat(msg, " signature: ");
-               utf_strcat(msg, m->descriptor);
+               utf_cat(msg, m->descriptor);
                strcat(msg, ") ");
        }
 
                strcat(msg, ") ");
        }
 
@@ -855,10 +1054,30 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 }
 
 
 }
 
 
+/* exceptions_throw_verifyerror ************************************************
+
+   Throws a java.lang.VerifyError for the VM system.
+
+*******************************************************************************/
+
+void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
+{
+       *exceptionptr = exceptions_new_verifyerror(m, message);
+}
+
+
 /* exceptions_throw_verifyerror_for_stack **************************************
 
    throws a java.lang.VerifyError for an invalid stack slot type
 
 /* exceptions_throw_verifyerror_for_stack **************************************
 
    throws a java.lang.VerifyError for an invalid stack slot type
 
+   IN:
+      m............method in which the error was found
+         type.........the expected type
+
+   RETURN VALUE:
+      an exception pointer (in any case -- either it is the newly created
+         exception, or an exception thrown while trying to create it).
+
 *******************************************************************************/
 
 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
 *******************************************************************************/
 
 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
@@ -873,9 +1092,9 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
        msglen = 0;
 
        if (m)
        msglen = 0;
 
        if (m)
-               msglen = strlen("(class: ") + utf_strlen(m->class->name) +
-                       strlen(", method: ") + utf_strlen(m->name) +
-                       strlen(" signature: ") + utf_strlen(m->descriptor) +
+               msglen = strlen("(class: ") + utf_bytes(m->class->name) +
+                       strlen(", method: ") + utf_bytes(m->name) +
+                       strlen(" signature: ") + utf_bytes(m->descriptor) +
                        strlen(") Expecting to find longest-------typename on stack") 
                        + strlen("0");
 
                        strlen(") Expecting to find longest-------typename on stack") 
                        + strlen("0");
 
@@ -887,11 +1106,11 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
 
        if (m) {
                strcpy(msg, "(class: ");
 
        if (m) {
                strcpy(msg, "(class: ");
-               utf_strcat(msg, m->class->name);
+               utf_cat_classname(msg, m->class->name);
                strcat(msg, ", method: ");
                strcat(msg, ", method: ");
-               utf_strcat(msg, m->name);
+               utf_cat(msg, m->name);
                strcat(msg, " signature: ");
                strcat(msg, " signature: ");
-               utf_strcat(msg, m->descriptor);
+               utf_cat(msg, m->descriptor);
                strcat(msg, ") ");
        }
        else {
                strcat(msg, ") ");
        }
        else {
@@ -905,7 +1124,8 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
                case TYPE_FLT: typename = "float"; break;
                case TYPE_DBL: typename = "double"; break;
                case TYPE_ADR: typename = "object/array"; break;
                case TYPE_FLT: typename = "float"; break;
                case TYPE_DBL: typename = "double"; break;
                case TYPE_ADR: typename = "object/array"; break;
-               default: assert(0);
+               case TYPE_RET: typename = "returnAddress"; break;
+               default:       typename = "<INVALID>"; assert(0); break;
        }
        strcat(msg, typename);
        strcat(msg, " on stack");
        }
        strcat(msg, typename);
        strcat(msg, " on stack");
@@ -921,6 +1141,7 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
        *exceptionptr = o;
 }
 
        *exceptionptr = o;
 }
 
+
 /* new_arithmeticexception *****************************************************
 
    Generates a java.lang.ArithmeticException for the jit compiler.
 /* new_arithmeticexception *****************************************************
 
    Generates a java.lang.ArithmeticException for the jit compiler.
@@ -966,7 +1187,7 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index)
        if (m == NULL)
                return *exceptionptr;
 
        if (m == NULL)
                return *exceptionptr;
 
-       o = vm_call_method_intern(m, (void *) (ptrint) index, NULL, NULL, NULL);
+       o = vm_call_method(m, NULL, index);
 
        s = (java_lang_String *) o;
 
 
        s = (java_lang_String *) o;
 
@@ -1003,13 +1224,13 @@ void exceptions_throw_arrayindexoutofboundsexception(void)
 }
 
 
 }
 
 
-/* new_arraystoreexception *****************************************************
+/* exceptions_new_arraystoreexception ******************************************
 
 
-   generates a java.lang.ArrayStoreException for the jit compiler
+   Generates a java.lang.ArrayStoreException for the VM compiler.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-java_objectheader *new_arraystoreexception(void)
+java_objectheader *exceptions_new_arraystoreexception(void)
 {
        java_objectheader *e;
 
 {
        java_objectheader *e;
 
@@ -1023,19 +1244,38 @@ java_objectheader *new_arraystoreexception(void)
 }
 
 
 }
 
 
-/* new_classcastexception ******************************************************
+/* exceptions_throw_arraystoreexception ****************************************
 
 
-   generates a java.lang.ClassCastException for the jit compiler
+   Generates a java.lang.ArrayStoreException for the VM system and
+   throw it in the VM system.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-java_objectheader *new_classcastexception(void)
+void exceptions_throw_arraystoreexception(void)
+{
+       *exceptionptr = exceptions_new_arraystoreexception();
+}
+
+
+/* exceptions_new_classcastexception *******************************************
+
+   Generates a java.lang.ClassCastException for the JIT compiler.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
 {
        java_objectheader *e;
 {
        java_objectheader *e;
+       utf               *classname;
+       java_lang_String  *s;
 
 
-       e = new_exception(string_java_lang_ClassCastException);
+       classname = o->vftbl->class->name;
 
 
-       if (!e)
+       s = javastring_new(classname);
+
+       e = native_new_and_init_string(class_java_lang_ClassCastException, s);
+
+       if (e == NULL)
                return *exceptionptr;
 
        return e;
                return *exceptionptr;
 
        return e;
@@ -1074,26 +1314,39 @@ void exceptions_throw_illegalargumentexception(void)
 }
 
 
 }
 
 
-/* new_illegalmonitorstateexception ********************************************
+/* exceptions_new_illegalmonitorstateexception *********************************
 
    Generates a java.lang.IllegalMonitorStateException for the VM
    thread system.
 
 *******************************************************************************/
 
 
    Generates a java.lang.IllegalMonitorStateException for the VM
    thread system.
 
 *******************************************************************************/
 
-java_objectheader *new_illegalmonitorstateexception(void)
+java_objectheader *exceptions_new_illegalmonitorstateexception(void)
 {
        java_objectheader *e;
 
        e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
 
 {
        java_objectheader *e;
 
        e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
 
-       if (!e)
+       if (e == NULL)
                return *exceptionptr;
 
        return e;
 }
 
 
                return *exceptionptr;
 
        return e;
 }
 
 
+/* exceptions_throw_illegalmonitorstateexception *******************************
+
+   Generates a java.lang.IllegalMonitorStateException for the VM
+   system and throw it in the VM system.
+
+*******************************************************************************/
+
+void exceptions_throw_illegalmonitorstateexception(void)
+{
+       *exceptionptr = exceptions_new_illegalmonitorstateexception();
+}
+
+
 /* exceptions_new_negativearraysizeexception ***********************************
 
    Generates a java.lang.NegativeArraySizeException for the VM system.
 /* exceptions_new_negativearraysizeexception ***********************************
 
    Generates a java.lang.NegativeArraySizeException for the VM system.
@@ -1157,15 +1410,91 @@ void exceptions_throw_nullpointerexception(void)
 }
 
 
 }
 
 
+/* exceptions_new_stringindexoutofboundsexception ******************************
+
+   Generates a java.lang.StringIndexOutOfBoundsException for the VM
+   system.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_stringindexoutofboundsexception(void)
+{
+       java_objectheader *e;
+
+       e = new_exception(string_java_lang_StringIndexOutOfBoundsException);
+
+       if (e == NULL)
+               return *exceptionptr;
+
+       return e;
+}
+
+
+/* exceptions_throw_stringindexoutofboundsexception ****************************
+
+   Throws a java.lang.StringIndexOutOfBoundsException for the VM
+   system.
+
+*******************************************************************************/
+
+void exceptions_throw_stringindexoutofboundsexception(void)
+{
+       *exceptionptr = exceptions_new_stringindexoutofboundsexception();
+}
+
+
+/* exceptions_get_and_clear_exception ******************************************
+
+   Gets the exception pointer of the current thread and clears it.
+   This function may return NULL.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_get_and_clear_exception(void)
+{
+       java_objectheader **p;
+       java_objectheader  *e;
+
+       /* get the pointer of the exception pointer */
+
+       p = exceptionptr;
+
+       /* get the exception */
+
+       e = *p;
+
+       /* and clear the exception */
+
+       *p = NULL;
+
+       /* return the exception */
+
+       return e;
+}
+
+
 /* exceptions_handle_exception *************************************************
 
 /* exceptions_handle_exception *************************************************
 
-   XXX
+   Try to find an exception handler for the given exception and return it.
+   If no handler is found, exit the monitor of the method (if any)
+   and return NULL.
+
+   IN:
+      xptr.........the exception object
+         xpc..........PC of where the exception was thrown
+         pv...........Procedure Value of the current method
+         sp...........current stack pointer
+
+   RETURN VALUE:
+      the address of the first matching exception handler, or
+         NULL if no handler was found
 
 *******************************************************************************/
 
 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
 {
        methodinfo            *m;
 
 *******************************************************************************/
 
 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
 {
        methodinfo            *m;
+       codeinfo              *code;
        s4                     framesize;
        s4                     issync;
        exceptionentry        *ex;
        s4                     framesize;
        s4                     issync;
        exceptionentry        *ex;
@@ -1173,22 +1502,29 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
        s4                     i;
        classref_or_classinfo  cr;
        classinfo             *c;
        s4                     i;
        classref_or_classinfo  cr;
        classinfo             *c;
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
        java_objectheader     *o;
 #endif
 
        java_objectheader     *o;
 #endif
 
-       /* get methodinfo pointer from method header */
+       /* get info from the method header */
 
 
-       m                    = *((methodinfo **)    (pv + MethodPointer));
+       code                 = *((codeinfo **)      (pv + CodeinfoPointer));
        framesize            = *((s4 *)             (pv + FrameSize));
        issync               = *((s4 *)             (pv + IsSync));
        ex                   =   (exceptionentry *) (pv + ExTableStart);
        exceptiontablelength = *((s4 *)             (pv + ExTableSize));
 
        framesize            = *((s4 *)             (pv + FrameSize));
        issync               = *((s4 *)             (pv + IsSync));
        ex                   =   (exceptionentry *) (pv + ExTableStart);
        exceptiontablelength = *((s4 *)             (pv + ExTableSize));
 
+       /* Get the methodinfo pointer from the codeinfo pointer. For
+          asm_vm_call_method the codeinfo pointer is NULL. */
+
+       m = (code == NULL) ? NULL : code->m;
+
+#if !defined(NDEBUG)
        /* print exception trace */
 
        if (opt_verbose || opt_verbosecall || opt_verboseexception)
                builtin_trace_exception(xptr, m, xpc, 1);
        /* print exception trace */
 
        if (opt_verbose || opt_verbosecall || opt_verboseexception)
                builtin_trace_exception(xptr, m, xpc, 1);
+#endif
 
        for (i = 0; i < exceptiontablelength; i++) {
                /* ATTENTION: keep this here, as we need to decrement the
 
        for (i = 0; i < exceptiontablelength; i++) {
                /* ATTENTION: keep this here, as we need to decrement the
@@ -1196,6 +1532,13 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                ex--;
 
 
                ex--;
 
+               /* 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 ((ex->startpc == NULL) && (ex->endpc == NULL))
+                       return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
+
                /* is the xpc is the current catch range */
 
                if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
                /* is the xpc is the current catch range */
 
                if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
@@ -1219,17 +1562,40 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
                        /* resolve or load/link the exception class */
 
                        if (IS_CLASSREF(cr)) {
                        /* resolve or load/link the exception class */
 
                        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.                              */
+
                                c = resolve_classref_eager(cr.ref);
 
                                c = resolve_classref_eager(cr.ref);
 
+                               if (c == NULL) {
+                                       /* Exception resolving the exception class, argh! */
+                                       return NULL;
+                               }
+
+                               /* 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 {
                                c = cr.cls;
 
                        } else {
                                c = cr.cls;
 
+                               /* XXX I don't think this case can ever happen. -Edwin */
                                if (!(c->state & CLASS_LOADED))
                                        /* use the methods' classloader */
                                        if (!load_class_from_classloader(c->name,
                                                                                                         m->class->classloader))
                                                return NULL;
 
                                if (!(c->state & CLASS_LOADED))
                                        /* use the methods' classloader */
                                        if (!load_class_from_classloader(c->name,
                                                                                                         m->class->classloader))
                                                return NULL;
 
+                               /* 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))
                                                return NULL;
                                if (!(c->state & CLASS_LINKED))
                                        if (!link_class(c))
                                                return NULL;
@@ -1252,7 +1618,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
                }
        }
 
                }
        }
 
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
        /* is this method synchronized? */
 
        if (issync) {
        /* is this method synchronized? */
 
        if (issync) {
@@ -1267,7 +1633,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                assert(o != NULL);
 
 
                assert(o != NULL);
 
-               builtin_monitorexit(o);
+               lock_monitor_exit(o);
        }
 #endif
 
        }
 #endif
 
@@ -1302,13 +1668,13 @@ void exceptions_print_exception(java_objectheader *xptr)
 
        /* print the root exception */
 
 
        /* print the root exception */
 
-       utf_display_classname(t->header.vftbl->class->name);
+       utf_display_printable_ascii_classname(t->header.vftbl->class->name);
 
        if (t->detailMessage) {
                u = javastring_toutf(t->detailMessage, false);
 
                printf(": ");
 
        if (t->detailMessage) {
                u = javastring_toutf(t->detailMessage, false);
 
                printf(": ");
-               utf_display(u);
+               utf_display_printable_ascii(u);
        }
 
        putc('\n', stdout);
        }
 
        putc('\n', stdout);
@@ -1317,13 +1683,13 @@ void exceptions_print_exception(java_objectheader *xptr)
 
        if (cause && (cause != t)) {
                printf("Caused by: ");
 
        if (cause && (cause != t)) {
                printf("Caused by: ");
-               utf_display_classname(cause->header.vftbl->class->name);
+               utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
 
                if (cause->detailMessage) {
                        u = javastring_toutf(cause->detailMessage, false);
 
                        printf(": ");
 
                if (cause->detailMessage) {
                        u = javastring_toutf(cause->detailMessage, false);
 
                        printf(": ");
-                       utf_display(u);
+                       utf_display_printable_ascii(u);
                }
 
                putc('\n', stdout);
                }
 
                putc('\n', stdout);