* renamed CACAO_TYPECHECK to ENABLE_VERIFIER
[cacao.git] / src / vm / exceptions.c
index 883f471f1bfbab9a71a418e5c8fcfe1b794894af..fe963e69072a28ce3d3cb08790197820bcbecd88 100644 (file)
@@ -26,9 +26,9 @@
 
    Authors: Christian Thalinger
 
-   Changes:
+   Changes: Edwin Steiner
 
-   $Id: exceptions.c 2490 2005-05-20 23:05:49Z twisti $
+   $Id: exceptions.c 3807 2005-11-26 21:51:11Z edwin $
 
 */
 
 #include "vm/jit/jit.h"
 
 
-/* for raising exceptions from native methods */
+/* for raising exceptions from native methods *********************************/
 
 #if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
-java_objectheader* _exceptionptr = NULL;
-u1 _dontfillinexceptionstacktrace = false;
+java_objectheader *_no_threads_exceptionptr = NULL;
 #endif
 
 
@@ -74,58 +73,91 @@ bool exceptions_init(void)
 {
        /* java/lang/Throwable */
 
-       if (!load_class_bootstrap(utf_java_lang_Throwable,
-                                                         &class_java_lang_Throwable) ||
+       if (!(class_java_lang_Throwable =
+                 load_class_bootstrap(utf_java_lang_Throwable)) ||
                !link_class(class_java_lang_Throwable))
                return false;
 
 
        /* java/lang/VMThrowable */
 
-       if (!load_class_bootstrap(utf_java_lang_VMThrowable,
-                                                         &class_java_lang_VMThrowable) ||
+       if (!(class_java_lang_VMThrowable =
+                 load_class_bootstrap(utf_java_lang_VMThrowable)) ||
                !link_class(class_java_lang_VMThrowable))
                return false;
 
 
        /* java/lang/Error */
 
-       if (!load_class_bootstrap(utf_java_lang_Error, &class_java_lang_Error) ||
+       if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
                !link_class(class_java_lang_Error))
                return false;
 
+       /* java/lang/NoClassDefFoundError */
 
-       /* java/lang/Exception */
-
-       if (!load_class_bootstrap(utf_java_lang_Exception,
-                                                         &class_java_lang_Exception) ||
-               !link_class(class_java_lang_Exception))
+       if (!(class_java_lang_NoClassDefFoundError =
+                 load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
+               !link_class(class_java_lang_NoClassDefFoundError))
                return false;
 
+       /* java/lang/LinkageError */
 
-       /* java/lang/NoClassDefFoundError */
-
-       if (!load_class_bootstrap(utf_java_lang_NoClassDefFoundError,
-                                                         &class_java_lang_NoClassDefFoundError) ||
-               !link_class(class_java_lang_NoClassDefFoundError))
+       if (!(class_java_lang_LinkageError =
+                 load_class_bootstrap(utf_java_lang_LinkageError)) ||
+               !link_class(class_java_lang_LinkageError))
                return false;
 
+       /* java/lang/NoSuchMethodError */
+
+       if (!(class_java_lang_NoSuchMethodError =
+                 load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
+               !link_class(class_java_lang_NoSuchMethodError))
+               return false;
 
        /* java/lang/OutOfMemoryError */
 
-       if (!load_class_bootstrap(utf_java_lang_OutOfMemoryError,
-                                                         &class_java_lang_OutOfMemoryError) ||
+       if (!(class_java_lang_OutOfMemoryError =
+                 load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
                !link_class(class_java_lang_OutOfMemoryError))
                return false;
 
 
+       /* java/lang/Exception */
+
+       if (!(class_java_lang_Exception =
+                 load_class_bootstrap(utf_java_lang_Exception)) ||
+               !link_class(class_java_lang_Exception))
+               return false;
+
        /* java/lang/ClassNotFoundException */
 
-       if (!load_class_bootstrap(utf_java_lang_ClassNotFoundException,
-                                                         &class_java_lang_ClassNotFoundException) ||
+       if (!(class_java_lang_ClassNotFoundException =
+                 load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
                !link_class(class_java_lang_ClassNotFoundException))
                return false;
 
+       /* java/lang/IllegalArgumentException */
+
+       if (!(class_java_lang_IllegalArgumentException =
+                 load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
+               !link_class(class_java_lang_IllegalArgumentException))
+               return false;
+
+       /* java/lang/IllegalMonitorStateException */
+
+       if (!(class_java_lang_IllegalMonitorStateException =
+                 load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
+               !link_class(class_java_lang_IllegalMonitorStateException))
+               return false;
+
+       /* java/lang/NullPointerException */
+
+       if (!(class_java_lang_NullPointerException =
+                 load_class_bootstrap(utf_java_lang_NullPointerException)) ||
+               !link_class(class_java_lang_NullPointerException))
+               return false;
+
+
        return true;
 }
 
@@ -159,8 +191,21 @@ static void throw_exception_exit_intern(bool doexit)
                        /* exception, so print it.                                        */
 
                        if (*exceptionptr) {
+                               java_lang_Throwable *t;
+
+                               t = (java_lang_Throwable *) *exceptionptr;
+
                                fprintf(stderr, "Exception while printStackTrace(): ");
-                               utf_fprint_classname(stderr, c->name);
+                               utf_fprint_classname(stderr, t->header.vftbl->class->name);
+
+                               if (t->detailMessage) {
+                                       char *buf;
+
+                                       buf = javastring_tochar((java_objectheader *) t->detailMessage);
+                                       fprintf(stderr, ": %s", buf);
+                                       MFREE(buf, char, strlen(buf));
+                               }
+                                       
                                fprintf(stderr, "\n");
                        }
 
@@ -247,72 +292,162 @@ void throw_cacao_exception_exit(const char *exception, const char *message, ...)
 }
 
 
+/* exceptions_throw_outofmemory_exit *******************************************
+
+   Just print an: java.lang.InternalError: Out of memory
+
+*******************************************************************************/
+
+void exceptions_throw_outofmemory_exit(void)
+{
+       throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                          "Out of memory");
+}
+
+
+/* new_exception ***************************************************************
+
+   Creates an exception object with the given name and initalizes it.
+
+*******************************************************************************/
+
 java_objectheader *new_exception(const char *classname)
 {
-       classinfo *c;
-   
-       if (!load_class_bootstrap(utf_new_char(classname), &c))
+       java_objectheader *o;
+       classinfo         *c;
+
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
                return *exceptionptr;
 
-       return native_new_and_init(c);
+       o = native_new_and_init(c);
+
+       if (!o)
+               return *exceptionptr;
+
+       return o;
 }
 
-java_objectheader *new_exception_message(const char *classname, const char *message)
+
+/* new_exception_message *******************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given char message.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_message(const char *classname,
+                                                                                const char *message)
 {
-       classinfo *c;
+       java_objectheader *o;
+       classinfo         *c;
    
-       if (!load_class_bootstrap(utf_new_char(classname), &c))
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
                return *exceptionptr;
 
+       o = native_new_and_init_string(c, javastring_new_char(message));
+
+       if (!o)
+               return *exceptionptr;
 
-       return native_new_and_init_string(c, javastring_new_char(message));
+       return o;
 }
 
 
-java_objectheader *new_exception_throwable(const char *classname, java_lang_Throwable *throwable)
+/* new_exception_throwable *****************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/Throwable exception.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_throwable(const char *classname,
+                                                                                  java_lang_Throwable *throwable)
 {
-       classinfo *c;
+       java_objectheader *o;
+       classinfo         *c;
    
-       if (!load_class_bootstrap(utf_new_char(classname), &c))
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
                return *exceptionptr;
 
+       o = native_new_and_init_throwable(c, throwable);
 
-       return native_new_and_init_throwable(c, throwable);
+       if (!o)
+               return *exceptionptr;
+
+       return o;
 }
 
 
+/* new_exception_utfmessage ****************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given utf message.
+
+*******************************************************************************/
+
 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
 {
-       classinfo *c;
+       java_objectheader *o;
+       classinfo         *c;
    
-       if (!load_class_bootstrap(utf_new_char(classname), &c))
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
                return *exceptionptr;
 
+       o = native_new_and_init_string(c, javastring_new(message));
+
+       if (!o)
+               return *exceptionptr;
 
-       return native_new_and_init_string(c, javastring_new(message));
+       return o;
 }
 
 
-java_objectheader *new_exception_javastring(const char *classname, java_lang_String *message)
+/* new_exception_javastring ****************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given java/lang/String message.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_javastring(const char *classname,
+                                                                                       java_lang_String *message)
 {
-       classinfo *c;
+       java_objectheader *o;
+       classinfo         *c;
    
-       if (!load_class_bootstrap(utf_new_char(classname), &c))
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
                return *exceptionptr;
 
+       o = native_new_and_init_string(c, message);
+
+       if (!o)
+               return *exceptionptr;
 
-       return native_new_and_init_string(c, message);
+       return o;
 }
 
 
+/* new_exception_int ***********************************************************
+
+   Creates an exception object with the given name and initalizes it
+   with the given int value.
+
+*******************************************************************************/
+
 java_objectheader *new_exception_int(const char *classname, s4 i)
 {
-       classinfo *c;
+       java_objectheader *o;
+       classinfo         *c;
    
-       if (!load_class_bootstrap(utf_new_char(classname), &c))
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
+               return *exceptionptr;
+
+       o = native_new_and_init_int(c, i);
+
+       if (!o)
                return *exceptionptr;
 
-       return native_new_and_init_int(c, i);
+       return o;
 }
 
 
@@ -331,8 +466,10 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 
        /* calculate message length */
 
+       msglen = 0;
+
        if (c)
-               msglen = utf_strlen(c->name) + strlen(" (");
+               msglen += utf_strlen(c->name) + strlen(" (");
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
@@ -369,6 +506,87 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 }
 
 
+/* new_classnotfoundexception **************************************************
+
+   Generates a java.lang.ClassNotFoundException for the classloader.
+
+*******************************************************************************/
+
+java_objectheader *new_classnotfoundexception(utf *name)
+{
+       java_objectheader *o;
+
+       o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
+                                                                  javastring_new(name));
+
+       if (!o)
+               return *exceptionptr;
+
+       return o;
+}
+
+
+/* new_noclassdeffounderror ****************************************************
+
+   Generates a java.lang.NoClassDefFoundError
+
+*******************************************************************************/
+
+java_objectheader *new_noclassdeffounderror(utf *name)
+{
+       java_objectheader *o;
+
+       o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
+                                                                  javastring_new(name));
+
+       if (!o)
+               return *exceptionptr;
+
+       return o;
+}
+
+
+/* classnotfoundexception_to_noclassdeffounderror ******************************
+
+   Check the *exceptionptr for a ClassNotFoundException. If it is one,
+   convert it to a NoClassDefFoundError.
+
+*******************************************************************************/
+
+void classnotfoundexception_to_noclassdeffounderror(void)
+{
+       java_objectheader *xptr;
+       java_objectheader *cause;
+
+       /* get the cause */
+
+       cause = *exceptionptr;
+
+       /* convert ClassNotFoundException's to NoClassDefFoundError's */
+
+       if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
+               /* clear exception, because we are calling jit code again */
+
+               *exceptionptr = NULL;
+
+               /* create new error */
+
+               xptr =
+                       new_exception_javastring(string_java_lang_NoClassDefFoundError,
+                                       ((java_lang_Throwable *) cause)->detailMessage);
+
+               /* we had an exception while creating the error */
+
+               if (*exceptionptr)
+                       return;
+
+               /* set new exception */
+
+               *exceptionptr = xptr;
+       }
+}
+
+
 /* new_internalerror ***********************************************************
 
    Generates a java.lang.InternalError for the VM.
@@ -410,6 +628,89 @@ 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.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_linkageerror(const char *message,
+                                                                                          classinfo *c)
+{
+       java_objectheader *o;
+       char              *msg;
+       s4                 msglen;
+
+       /* calculate exception message length */
+
+       msglen = strlen(message) + 1;
+       if (c) {
+               msglen += utf_strlen(c->name);
+       }
+               
+       /* allocate memory */
+
+       msg = MNEW(char, msglen);
+
+       /* generate message */
+
+       strcpy(msg,message);
+       if (c) {
+               utf_strcat(msg, c->name);
+       }
+
+       o = native_new_and_init_string(class_java_lang_LinkageError,
+                                                                  javastring_new_char(msg));
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
+
+       return o;
+}
+
+
+/* exceptions_new_nosuchmethoderror ********************************************
+
+   Generates a java.lang.NoSuchMethodError with an error message.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
+                                                                                                       utf *name, utf *desc)
+{
+       java_objectheader *o;
+       char              *msg;
+       s4                 msglen;
+
+       /* calculate exception message length */
+
+       msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
+               utf_strlen(desc) + strlen("0");
+
+       /* allocate memory */
+
+       msg = MNEW(char, msglen);
+
+       /* generate message */
+
+       utf_sprint(msg, c->name);
+       strcat(msg, ".");
+       utf_strcat(msg, name);
+       utf_strcat(msg, desc);
+
+       o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
+                                                                  javastring_new_char(msg));
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
+
+       return o;
+}
+
+
 /* new_unsupportedclassversionerror ********************************************
 
    generates a java.lang.UnsupportedClassVersionError for the classloader
@@ -476,10 +777,13 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 
        /* calculate exception message length */
 
-       msglen = strlen("(class: ") + utf_strlen(m->class->name) +
-               strlen(", method: ") + utf_strlen(m->name) +
-               strlen(" signature: ") + utf_strlen(m->descriptor) +
-               strlen(") ") + strlen("0");
+       msglen = 0;
+
+       if (m)
+               msglen = strlen("(class: ") + utf_strlen(m->class->name) +
+                       strlen(", method: ") + utf_strlen(m->name) +
+                       strlen(" signature: ") + utf_strlen(m->descriptor) +
+                       strlen(") ") + strlen("0");
 
        va_start(ap, message);
        msglen += get_variable_message_length(message, ap);
@@ -491,13 +795,15 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 
        /* generate message */
 
-       strcpy(msg, "(class: ");
-       utf_strcat(msg, m->class->name);
-       strcat(msg, ", method: ");
-       utf_strcat(msg, m->name);
-       strcat(msg, " signature: ");
-       utf_strcat(msg, m->descriptor);
-       strcat(msg, ") ");
+       if (m) {
+               strcpy(msg, "(class: ");
+               utf_strcat(msg, m->class->name);
+               strcat(msg, ", method: ");
+               utf_strcat(msg, m->name);
+               strcat(msg, " signature: ");
+               utf_strcat(msg, m->descriptor);
+               strcat(msg, ") ");
+       }
 
        va_start(ap, message);
        vsprintf(msg + strlen(msg), message, ap);
@@ -589,6 +895,7 @@ java_objectheader *new_arraystoreexception(void)
        java_objectheader *e;
 
        e = new_exception(string_java_lang_ArrayStoreException);
+/*     e = native_new_and_init(class_java_lang_ArrayStoreException); */
 
        if (!e)
                return *exceptionptr;
@@ -616,6 +923,41 @@ java_objectheader *new_classcastexception(void)
 }
 
 
+/* new_illegalargumentexception ************************************************
+
+   Generates a java.lang.IllegalArgumentException for the VM system.
+
+*******************************************************************************/
+
+java_objectheader *new_illegalargumentexception(void)
+{
+       java_objectheader *e;
+
+       if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException)))
+               return *exceptionptr;
+
+       return e;
+}
+
+
+/* new_illegalmonitorstateexception ********************************************
+
+   Generates a java.lang.IllegalMonitorStateException for the VM
+   thread system.
+
+*******************************************************************************/
+
+java_objectheader *new_illegalmonitorstateexception(void)
+{
+       java_objectheader *e;
+
+       if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException)))
+               return *exceptionptr;
+
+       return e;
+}
+
+
 /* new_negativearraysizeexception **********************************************
 
    generates a java.lang.NegativeArraySizeException for the jit compiler
@@ -645,7 +987,7 @@ java_objectheader *new_nullpointerexception(void)
 {
        java_objectheader *e;
 
-       e = new_exception(string_java_lang_NullPointerException);
+       e = native_new_and_init(class_java_lang_NullPointerException);
 
        if (!e)
                return *exceptionptr;
@@ -654,6 +996,53 @@ java_objectheader *new_nullpointerexception(void)
 }
 
 
+/* exceptions_print_exception **************************************************
+
+   Prints an exception, the detail message and the cause, if
+   available, with CACAO internal functions to stdout.
+
+*******************************************************************************/
+
+void exceptions_print_exception(java_objectheader *xptr)
+{
+       java_lang_Throwable   *t;
+       java_lang_Throwable   *cause;
+       utf                   *u;
+
+       t = (java_lang_Throwable *) xptr;
+       cause = t->cause;
+
+       /* print the root exception */
+
+       utf_display_classname(t->header.vftbl->class->name);
+
+       if (t->detailMessage) {
+               u = javastring_toutf(t->detailMessage, false);
+
+               printf(": ");
+               utf_display(u);
+       }
+
+       putc('\n', stdout);
+
+       /* print the cause if available */
+
+       if (cause && (cause != t)) {
+               printf("Caused by: ");
+               utf_display_classname(cause->header.vftbl->class->name);
+
+               if (cause->detailMessage) {
+                       u = javastring_toutf(cause->detailMessage, false);
+
+                       printf(": ");
+                       utf_display(u);
+               }
+
+               putc('\n', stdout);
+       }
+}
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where