* src/vm/jit/cfg.c (cfg_build): Removed set-but-not-used variable (m).
[cacao.git] / src / vm / exceptions.c
index 7eeff1eb314083511d953af7b9510ccae24d0d04..b37dd50252e71f0c74a72f91ed1c75d85e41a102 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/exceptions.c - exception related functions
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Christian Thalinger
 
    Changes: Edwin Steiner
 
-   $Id: exceptions.c 4147 2006-01-12 21:07:11Z twisti $
+   $Id: exceptions.c 5866 2006-10-30 11:00:56Z edwin $
 
 */
 
@@ -54,6 +54,7 @@
 #include "vm/loader.h"
 #include "vm/options.h"
 #include "vm/stringlocal.h"
+#include "vm/vm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/methodheader.h"
@@ -61,7 +62,7 @@
 
 /* for raising exceptions from native methods *********************************/
 
-#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
+#if !defined(ENABLE_THREADS)
 java_objectheader *_no_threads_exceptionptr = NULL;
 #endif
 
@@ -96,11 +97,11 @@ bool exceptions_init(void)
                !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 */
@@ -110,6 +111,13 @@ bool exceptions_init(void)
                !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 =
@@ -132,6 +140,13 @@ bool exceptions_init(void)
                !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 =
@@ -188,7 +203,7 @@ static void throw_exception_exit_intern(bool doexit)
                /* print the stacktrace */
 
                if (pss) {
-                       ASM_CALLJAVAFUNCTION(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      */
@@ -200,7 +215,7 @@ static void throw_exception_exit_intern(bool doexit)
                                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;
@@ -214,7 +229,7 @@ static void throw_exception_exit_intern(bool doexit)
                        }
 
                } else {
-                       utf_fprint_classname(stderr, c->name);
+                       utf_fprint_printable_ascii_classname(stderr, c->name);
                        fprintf(stderr, ": printStackTrace()V not found!\n");
                }
 
@@ -313,6 +328,13 @@ void exceptions_throw_outofmemory_exit(void)
 
    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)
@@ -337,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.
 
+   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 *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 o;
+       return new_exception_javastring(classname, s);
 }
 
 
@@ -362,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.
 
+   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,
@@ -387,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.
 
+   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 *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 o;
+       return new_exception_javastring(classname, s);
 }
 
 
@@ -411,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.
 
+   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,
@@ -436,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.
 
+   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)
@@ -455,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
 
+   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, ...)
@@ -473,7 +592,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
        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);
@@ -491,7 +610,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
        /* print message into allocated buffer */
 
        if (c) {
-               utf_sprint_classname(msg, c->name);
+               utf_copy_classname(msg, c->name);
                strcat(msg, " (");
        }
 
@@ -512,8 +631,15 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 
 /* 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).
 
 *******************************************************************************/
 
@@ -531,14 +657,25 @@ void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
 
    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_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;
@@ -551,14 +688,25 @@ java_objectheader *new_classnotfoundexception(utf *name)
 
    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_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;
@@ -612,6 +760,13 @@ void classnotfoundexception_to_noclassdeffounderror(void)
 
    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, ...)
@@ -652,7 +807,15 @@ java_objectheader *new_internalerror(const char *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).
 
 *******************************************************************************/
 
@@ -667,7 +830,7 @@ java_objectheader *exceptions_new_linkageerror(const char *message,
 
        msglen = strlen(message) + 1;
        if (c) {
-               msglen += utf_strlen(c->name);
+               msglen += utf_bytes(c->name);
        }
                
        /* allocate memory */
@@ -678,16 +841,19 @@ java_objectheader *exceptions_new_linkageerror(const char *message,
 
        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,
-                                                                  javastring_new_char(msg));
+                                                                  javastring_new_from_utf_string(msg));
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
+       if (!o)
+               return *exceptionptr;
+
        return o;
 }
 
@@ -696,6 +862,15 @@ java_objectheader *exceptions_new_linkageerror(const char *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,
@@ -707,8 +882,8 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
 
        /* 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 */
 
@@ -716,25 +891,53 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
 
        /* generate message */
 
-       utf_sprint(msg, c->name);
+       utf_copy_classname(msg, c->name);
        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,
-                                                                  javastring_new_char(msg));
+                                                                  javastring_new_from_utf_string(msg));
 
        /* free memory */
 
        MFREE(msg, char, msglen);
 
+       if (!o)
+               return *exceptionptr;
+
        return o;
 }
 
 
+/* exceptions_throw_nosuchmethoderror ******************************************
+
+   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)
+{
+       *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
+}
+
+
 /* 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).
 
 *******************************************************************************/
 
@@ -747,7 +950,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 
        /* 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);
@@ -759,7 +962,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 
        /* generate message */
 
-       utf_sprint_classname(msg, c->name);
+       utf_copy_classname(msg, c->name);
        strcat(msg, " (");
 
        va_start(ap, message);
@@ -781,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.
+
+   IN:
+      m............method in which the error was found
+         message......UTF-8 format string
 
-   generates a java.lang.VerifyError for the jit compiler
+   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;
@@ -801,9 +1013,9 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
        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);
@@ -818,11 +1030,11 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 
        if (m) {
                strcpy(msg, "(class: ");
-               utf_strcat(msg, m->class->name);
+               utf_cat_classname(msg, m->class->name);
                strcat(msg, ", method: ");
-               utf_strcat(msg, m->name);
+               utf_cat(msg, m->name);
                strcat(msg, " signature: ");
-               utf_strcat(msg, m->descriptor);
+               utf_cat(msg, m->descriptor);
                strcat(msg, ") ");
        }
 
@@ -842,6 +1054,94 @@ 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
+
+   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)
+{
+       java_objectheader *o;
+       char              *msg;
+       s4                 msglen;
+       char              *typename;
+
+       /* calculate exception message length */
+
+       msglen = 0;
+
+       if (m)
+               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");
+
+       /* allocate memory */
+
+       msg = MNEW(char, msglen);
+
+       /* generate message */
+
+       if (m) {
+               strcpy(msg, "(class: ");
+               utf_cat_classname(msg, m->class->name);
+               strcat(msg, ", method: ");
+               utf_cat(msg, m->name);
+               strcat(msg, " signature: ");
+               utf_cat(msg, m->descriptor);
+               strcat(msg, ") ");
+       }
+       else {
+               msg[0] = 0;
+       }
+
+       strcat(msg,"Expecting to find ");
+       switch (type) {
+               case TYPE_INT: typename = "integer"; break;
+               case TYPE_LNG: typename = "long"; break;
+               case TYPE_FLT: typename = "float"; break;
+               case TYPE_DBL: typename = "double"; break;
+               case TYPE_ADR: typename = "object/array"; break;
+               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(string_java_lang_VerifyError, msg);
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
+
+       *exceptionptr = o;
+}
+
+
 /* new_arithmeticexception *****************************************************
 
    Generates a java.lang.ArithmeticException for the jit compiler.
@@ -884,20 +1184,20 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index)
                                                                 class_java_lang_Object,
                                                                 true);
 
-       if (!m)
+       if (m == NULL)
                return *exceptionptr;
 
-       ASM_CALLJAVAFUNCTION_ADR(o, m, (void *) (ptrint) index, NULL, NULL, NULL);
+       o = vm_call_method(m, NULL, index);
 
        s = (java_lang_String *) o;
 
-       if (!s)
+       if (s == NULL)
                return *exceptionptr;
 
        e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
                                                                 s);
 
-       if (!e)
+       if (e == NULL)
                return *exceptionptr;
 
        return e;
@@ -924,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;
 
@@ -944,19 +1244,38 @@ java_objectheader *new_arraystoreexception(void)
 }
 
 
-/* new_classcastexception ******************************************************
+/* exceptions_throw_arraystoreexception ****************************************
+
+   Generates a java.lang.ArrayStoreException for the VM system and
+   throw it in the VM system.
+
+*******************************************************************************/
+
+void exceptions_throw_arraystoreexception(void)
+{
+       *exceptionptr = exceptions_new_arraystoreexception();
+}
+
+
+/* exceptions_new_classcastexception *******************************************
 
-   generates a java.lang.ClassCastException for the jit compiler
+   Generates a java.lang.ClassCastException for the JIT compiler.
 
 *******************************************************************************/
 
-java_objectheader *new_classcastexception(void)
+java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
 {
        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;
@@ -995,26 +1314,39 @@ void exceptions_throw_illegalargumentexception(void)
 }
 
 
-/* new_illegalmonitorstateexception ********************************************
+/* exceptions_new_illegalmonitorstateexception *********************************
 
    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);
 
-       if (!e)
+       if (e == NULL)
                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.
@@ -1078,47 +1410,121 @@ 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 *************************************************
 
-   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
 
 *******************************************************************************/
 
+#if defined(ENABLE_JIT)
 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
 {
        methodinfo            *m;
-       s4                     framesize;
+       codeinfo              *code;
        s4                     issync;
-       exceptionentry        *ex;
+       dseg_exception_entry  *ex;
        s4                     exceptiontablelength;
        s4                     i;
        classref_or_classinfo  cr;
        classinfo             *c;
+#if defined(ENABLE_THREADS)
        java_objectheader     *o;
+#endif
 
-       /* get methodinfo pointer from method header */
+       /* get info from the method header */
 
-       m                    = *((methodinfo **)    (pv + MethodPointer));
-       framesize            = *((s4 *)             (pv + FrameSize));
+       code                 = *((codeinfo **)      (pv + CodeinfoPointer));
        issync               = *((s4 *)             (pv + IsSync));
-       ex                   =   (exceptionentry *) (pv + ExTableStart);
+       ex                   =   (dseg_exception_entry *) 
+                                                                                               (pv + ExTableStart);
        exceptiontablelength = *((s4 *)             (pv + ExTableSize));
 
-#if 0
-       if (m != NULL) {
-               printf("exceptions_handle_exception(%p, %p, %p, %p): ", xptr, xpc, pv, sp);
-               utf_display(m->class->name);
-               printf(".");
-               utf_display(m->name);
-               utf_display(m->descriptor);
-               printf(", %d\n", exceptiontablelength);
-       }
-#endif
+       /* 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 || runverbose || opt_verboseexception)
+       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
@@ -1126,30 +1532,70 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                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) {
+               if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
                        cr = ex->catchtype;
 
                        /* NULL catches everything */
 
-                       if (cr.any == NULL)
+                       if (cr.any == NULL) {
+#if !defined(NDEBUG)
+                               /* Print stacktrace of exception when caught. */
+
+                               if (opt_verboseexception) {
+                                       exceptions_print_exception(xptr);
+                                       stacktrace_print_trace(xptr);
+                               }
+#endif
+
                                return ex->handlerpc;
+                       }
 
                        /* 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);
 
+                               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;
 
+                               /* 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;
 
+                               /* 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;
@@ -1157,12 +1603,22 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                        /* is the thrown exception an instance of the catch class? */
 
-                       if (builtin_instanceof(xptr, c))
+                       if (builtin_instanceof(xptr, c)) {
+#if !defined(NDEBUG)
+                               /* Print stacktrace of exception when caught. */
+
+                               if (opt_verboseexception) {
+                                       exceptions_print_exception(xptr);
+                                       stacktrace_print_trace(xptr);
+                               }
+#endif
+
                                return ex->handlerpc;
+                       }
                }
        }
 
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
        /* is this method synchronized? */
 
        if (issync) {
@@ -1177,7 +1633,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                assert(o != NULL);
 
-               builtin_monitorexit(o);
+               lock_monitor_exit(o);
        }
 #endif
 
@@ -1185,6 +1641,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
        return NULL;
 }
+#endif /* defined(ENABLE_JIT) */
 
 
 /* exceptions_print_exception **************************************************
@@ -1194,7 +1651,6 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
 *******************************************************************************/
 
-#if !defined(NDEBUG)
 void exceptions_print_exception(java_objectheader *xptr)
 {
        java_lang_Throwable   *t;
@@ -1202,38 +1658,43 @@ void exceptions_print_exception(java_objectheader *xptr)
        utf                   *u;
 
        t = (java_lang_Throwable *) xptr;
+
+       if (t == NULL) {
+               puts("NULL\n");
+               return;
+       }
+
        cause = t->cause;
 
        /* 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(": ");
-               utf_display(u);
+               utf_display_printable_ascii(u);
        }
 
        putc('\n', stdout);
 
        /* print the cause if available */
 
-       if (cause && (cause != t)) {
+       if ((cause != NULL) && (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(": ");
-                       utf_display(u);
+                       utf_display_printable_ascii(u);
                }
 
                putc('\n', stdout);
        }
 }
-#endif /* !defined(NDEBUG) */
 
 
 /*
@@ -1247,4 +1708,5 @@ void exceptions_print_exception(java_objectheader *xptr)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */