* Small typo
[cacao.git] / src / vm / exceptions.c
index 4272acab1ec19dbbd6a849eef8383c8f618e4c37..b0a4cba7a6612073ecdbe3108300c0208a03a03a 100644 (file)
@@ -1,4 +1,4 @@
-/* vm/exceptions.c - exception related functions
+/* 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,
@@ -26,7 +26,9 @@
 
    Authors: Christian Thalinger
 
-   $Id: exceptions.c 1774 2004-12-20 20:16:57Z jowenn $
+   Changes:
+
+   $Id: exceptions.c 2671 2005-06-13 14:29:42Z twisti $
 
 */
 
 #include <stdarg.h>
 #include <stdlib.h>
 
+#include "config.h"
+
 #include "mm/memory.h"
 #include "native/native.h"
 #include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
 #include "toolbox/logging.h"
+#include "toolbox/util.h"
+#include "vm/class.h"
+#include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/stringlocal.h"
 #include "vm/tables.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
-#include "vm/options.h"
-
-
-/* system exception classes required in cacao */
-
-classinfo *class_java_lang_Throwable;
-classinfo *class_java_lang_Exception;
-classinfo *class_java_lang_Error;
-classinfo *class_java_lang_OutOfMemoryError;
-
-
-/* exception/error super class */
-
-char *string_java_lang_Throwable =
-    "java/lang/Throwable";
-
-char *string_java_lang_VMThrowable =
-    "java/lang/VMThrowable";
-
-
-/* specify some exception strings for code generation */
-
-char *string_java_lang_ArithmeticException =
-    "java/lang/ArithmeticException";
-
-char *string_java_lang_ArithmeticException_message =
-    "/ by zero";
-
-char *string_java_lang_ArrayIndexOutOfBoundsException =
-    "java/lang/ArrayIndexOutOfBoundsException";
-
-char *string_java_lang_ArrayStoreException =
-    "java/lang/ArrayStoreException";
-
-char *string_java_lang_ClassCastException =
-    "java/lang/ClassCastException";
-
-char *string_java_lang_ClassNotFoundException =
-       "java/lang/ClassNotFoundException";
-
-char *string_java_lang_CloneNotSupportedException =
-    "java/lang/CloneNotSupportedException";
-
-char *string_java_lang_Exception =
-    "java/lang/Exception";
-
-char *string_java_lang_IllegalAccessException =
-    "java/lang/IllegalAccessException";
-
-char *string_java_lang_IllegalArgumentException =
-    "java/lang/IllegalArgumentException";
-
-char *string_java_lang_IllegalMonitorStateException =
-    "java/lang/IllegalMonitorStateException";
-
-char *string_java_lang_IndexOutOfBoundsException =
-    "java/lang/IndexOutOfBoundsException";
-
-char *string_java_lang_InterruptedException =
-    "java/lang/InterruptedException";
 
-char *string_java_lang_NegativeArraySizeException =
-    "java/lang/NegativeArraySizeException";
 
-char *string_java_lang_NoSuchFieldException =
-       "java/lang/NoSuchFieldException";
+/* for raising exceptions from native methods */
 
-char *string_java_lang_NoSuchMethodException =
-       "java/lang/NoSuchMethodException";
-
-char *string_java_lang_NullPointerException =
-    "java/lang/NullPointerException";
-
-
-/* specify some error strings for code generation */
-
-char *string_java_lang_AbstractMethodError =
-    "java/lang/AbstractMethodError";
-
-char *string_java_lang_ClassCircularityError =
-    "java/lang/ClassCircularityError";
-
-char *string_java_lang_ClassFormatError =
-    "java/lang/ClassFormatError";
-
-char *string_java_lang_Error =
-    "java/lang/Error";
-
-char *string_java_lang_ExceptionInInitializerError =
-    "java/lang/ExceptionInInitializerError";
-
-char *string_java_lang_IncompatibleClassChangeError =
-    "java/lang/IncompatibleClassChangeError";
-
-char *string_java_lang_InternalError =
-    "java/lang/InternalError";
-
-char *string_java_lang_LinkageError =
-    "java/lang/LinkageError";
-
-char *string_java_lang_NoClassDefFoundError =
-    "java/lang/NoClassDefFoundError";
-
-char *string_java_lang_NoSuchFieldError =
-       "java/lang/NoSuchFieldError";
-
-char *string_java_lang_NoSuchMethodError =
-       "java/lang/NoSuchMethodError";
-
-char *string_java_lang_OutOfMemoryError =
-    "java/lang/OutOfMemoryError";
-
-char *string_java_lang_UnsupportedClassVersionError =
-    "java/lang/UnsupportedClassVersionError";
-
-char *string_java_lang_VerifyError =
-    "java/lang/VerifyError";
-
-char *string_java_lang_VirtualMachineError =
-    "java/lang/VirtualMachineError";
+#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
+java_objectheader* _exceptionptr = NULL;
+u1 _dontfillinexceptionstacktrace = false;
+#endif
 
 
-/* init_system_exceptions *****************************************************
+/* init_system_exceptions ******************************************************
 
-   load, link and compile exceptions used in the system
+   Load and link exceptions used in the system.
 
 *******************************************************************************/
 
-bool init_system_exceptions(void)
+bool exceptions_init(void)
 {
        /* java/lang/Throwable */
 
-       class_java_lang_Throwable =
-               class_new(utf_new_char(string_java_lang_Throwable));
-
-       if (!class_load(class_java_lang_Throwable))
+       if (!(class_java_lang_Throwable =
+                 load_class_bootstrap(utf_java_lang_Throwable)) ||
+               !link_class(class_java_lang_Throwable))
                return false;
 
-       if (!class_link(class_java_lang_Throwable))
-               return false;
 
+       /* java/lang/VMThrowable */
 
-       /* java/lang/Exception */
+       if (!(class_java_lang_VMThrowable =
+                 load_class_bootstrap(utf_java_lang_VMThrowable)) ||
+               !link_class(class_java_lang_VMThrowable))
+               return false;
 
-       class_java_lang_Exception =
-               class_new(utf_new_char(string_java_lang_Exception));
 
-       if (!class_load(class_java_lang_Exception))
-               return false;
+       /* java/lang/Error */
 
-       if (!class_link(class_java_lang_Exception))
+       if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
+               !link_class(class_java_lang_Error))
                return false;
 
 
-       /* java/lang/Error */
-
-       class_java_lang_Error =
-               class_new(utf_new_char(string_java_lang_Error));
+       /* java/lang/Exception */
 
-       if (!class_load(class_java_lang_Error))
+       if (!(class_java_lang_Exception =
+                 load_class_bootstrap(utf_java_lang_Exception)) ||
+               !link_class(class_java_lang_Exception))
                return false;
 
-       if (!class_link(class_java_lang_Error))
+
+       /* 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/OutOfMemoryError */
 
-       class_java_lang_OutOfMemoryError =
-               class_new(utf_new_char(string_java_lang_OutOfMemoryError));
-
-       if (!class_load(class_java_lang_OutOfMemoryError))
+       if (!(class_java_lang_OutOfMemoryError =
+                 load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
+               !link_class(class_java_lang_OutOfMemoryError))
                return false;
 
-       if (!class_link(class_java_lang_OutOfMemoryError))
+
+       /* java/lang/ClassNotFoundException */
+
+       if (!(class_java_lang_ClassNotFoundException =
+                 load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
+               !link_class(class_java_lang_ClassNotFoundException))
                return false;
 
        return true;
@@ -241,8 +145,8 @@ static void throw_exception_exit_intern(bool doexit)
                c = xptr->vftbl->class;
 
                pss = class_resolveclassmethod(c,
-                                                                          utf_new_char("printStackTrace"),
-                                                                          utf_new_char("()V"),
+                                                                          utf_printStackTrace,
+                                                                          utf_void__void,
                                                                           class_java_lang_Object,
                                                                           false);
 
@@ -250,9 +154,12 @@ static void throw_exception_exit_intern(bool doexit)
                if (pss) {
                        asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
 
-                       /* this normally means, we are EXTREMLY out of memory, but may be
-                          any other exception */
+                       /* This normally means, we are EXTREMLY out of memory or have a   */
+                       /* serious problem while printStackTrace. But may be another      */
+                       /* exception, so print it.                                        */
+
                        if (*exceptionptr) {
+                               fprintf(stderr, "Exception while printStackTrace(): ");
                                utf_fprint_classname(stderr, c->name);
                                fprintf(stderr, "\n");
                        }
@@ -265,26 +172,26 @@ static void throw_exception_exit_intern(bool doexit)
                fflush(stderr);
 
                /* good bye! */
-               if (doexit) {
+
+               if (doexit)
                        exit(1);
-               }
        }
 }
 
 
-void throw_exception()
+void throw_exception(void)
 {
        throw_exception_exit_intern(false);
 }
 
 
-void throw_exception_exit()
+void throw_exception_exit(void)
 {
        throw_exception_exit_intern(true);
 }
 
 
-void throw_main_exception()
+void throw_main_exception(void)
 {
        fprintf(stderr, "Exception in thread \"main\" ");
        fflush(stderr);
@@ -293,7 +200,7 @@ void throw_main_exception()
 }
 
 
-void throw_main_exception_exit()
+void throw_main_exception_exit(void)
 {
        fprintf(stderr, "Exception in thread \"main\" ");
        fflush(stderr);
@@ -316,9 +223,8 @@ void throw_cacao_exception_exit(const char *exception, const char *message, ...)
 
        /* convert to classname */
 
-       for (i = len - 1; i >= 0; i--) {
+       for (i = len - 1; i >= 0; i--)
                if (tmp[i] == '/') tmp[i] = '.';
-       }
 
        fprintf(stderr, "Exception in thread \"main\" %s", tmp);
 
@@ -336,69 +242,154 @@ void throw_cacao_exception_exit(const char *exception, const char *message, ...)
        fflush(stderr);
 
        /* good bye! */
+
        exit(1);
 }
 
 
-#if 1
-#define CREATENEW_EXCEPTION(ex) \
-    return ex;
-#else
-#define CREATENEW_EXCEPTION(ex) \
-       java_objectheader *newEx; \
-       java_objectheader *oldexception=*exceptionptr;\
-       *exceptionptr=0;\
-       newEx=ex;\
-       *exceptionptr=oldexception;\
-       return newEx;
-#endif
+/* new_exception ***************************************************************
+
+   Creates an exception object with the given name and initalizes it.
+
+*******************************************************************************/
 
-java_objectheader *new_exception(char *classname)
+java_objectheader *new_exception(const char *classname)
 {
-       classinfo *c = class_new(utf_new_char(classname));
+       java_objectheader *o;
+       classinfo         *c;
+
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
+               return *exceptionptr;
+
+       o = native_new_and_init(c);
+
+       if (!o)
+               return *exceptionptr;
 
-       CREATENEW_EXCEPTION(native_new_and_init(c));
+       return o;
 }
 
-java_objectheader *new_exception_message(char *classname, 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 = class_new(utf_new_char(classname));
+       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_char(message));
 
-       CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new_char(message)));
+       if (!o)
+               return *exceptionptr;
+
+       return o;
 }
 
 
-java_objectheader *new_exception_throwable(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 = class_new(utf_new_char(classname));
+       java_objectheader *o;
+       classinfo         *c;
+   
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
+               return *exceptionptr;
+
+       o = native_new_and_init_throwable(c, throwable);
+
+       if (!o)
+               return *exceptionptr;
 
-       CREATENEW_EXCEPTION(native_new_and_init_throwable(c, throwable));
+       return o;
 }
 
 
-java_objectheader *new_exception_utfmessage(char *classname, utf *message)
+/* 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 = class_new(utf_new_char(classname));
+       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));
+
+       if (!o)
+               return *exceptionptr;
 
-       CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new(message)));
+       return o;
 }
 
 
-java_objectheader *new_exception_javastring(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 = class_new(utf_new_char(classname));
+       java_objectheader *o;
+       classinfo         *c;
+   
+       if (!(c = load_class_bootstrap(utf_new_char(classname))))
+               return *exceptionptr;
+
+       o = native_new_and_init_string(c, message);
 
-       CREATENEW_EXCEPTION(native_new_and_init_string(c, message));
+       if (!o)
+               return *exceptionptr;
+
+       return o;
 }
 
 
-java_objectheader *new_exception_int(char *classname, s4 i)
+/* 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 (!(c = load_class_bootstrap(utf_new_char(classname))))
+               return *exceptionptr;
 
-       c = class_new(utf_new_char(classname));
+       o = native_new_and_init_int(c, i);
 
-       CREATENEW_EXCEPTION(native_new_and_init_int(c, i));
+       if (!o)
+               return *exceptionptr;
+
+       return o;
 }
 
 
@@ -408,21 +399,93 @@ java_objectheader *new_exception_int(char *classname, s4 i)
 
 *******************************************************************************/
 
-java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
+java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
 {
-       char msg[MAXLOGTEXT];
-       va_list ap;
+       java_objectheader *o;
+       char              *msg;
+       s4                 msglen;
+       va_list            ap;
 
-       utf_sprint_classname(msg, c->name);
-       sprintf(msg + strlen(msg), " (");
+       /* calculate message length */
+
+       msglen = 0;
+
+       if (c)
+               msglen += utf_strlen(c->name) + strlen(" (");
+
+       va_start(ap, message);
+       msglen += get_variable_message_length(message, ap);
+       va_end(ap);
+
+       if (c)
+               msglen += strlen(")");
+
+       msglen += strlen("0");
+
+       /* allocate a buffer */
+
+       msg = MNEW(char, msglen);
+
+       /* print message into allocated buffer */
+
+       if (c) {
+               utf_sprint_classname(msg, c->name);
+               strcat(msg, " (");
+       }
 
        va_start(ap, message);
        vsprintf(msg + strlen(msg), message, ap);
        va_end(ap);
 
-       sprintf(msg + strlen(msg), ")");
+       if (c)
+               strcat(msg, ")");
+
+       o = new_exception_message(string_java_lang_ClassFormatError, msg);
+
+       MFREE(msg, char, msglen);
+
+       return o;
+}
+
+
+/* new_internalerror ***********************************************************
+
+   Generates a java.lang.InternalError for the VM.
+
+*******************************************************************************/
+
+java_objectheader *new_internalerror(const char *message, ...)
+{
+       java_objectheader *o;
+       va_list            ap;
+       char              *msg;
+       s4                 msglen;
+
+       /* calculate exception message length */
+
+       va_start(ap, message);
+       msglen = get_variable_message_length(message, ap);
+       va_end(ap);
+
+       /* allocate memory */
+
+       msg = MNEW(char, msglen);
+
+       /* generate message */
+
+       va_start(ap, message);
+       vsprintf(msg, message, ap);
+       va_end(ap);
 
-       return new_exception_message(string_java_lang_ClassFormatError, msg);
+       /* create exception object */
+
+       o = new_exception_message(string_java_lang_InternalError, msg);
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
+
+       return o;
 }
 
 
@@ -432,22 +495,46 @@ java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
 
 *******************************************************************************/
 
-java_objectheader *new_unsupportedclassversionerror(classinfo *c, char *message, ...)
+java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
 {
-       char msg[MAXLOGTEXT];
-       va_list ap;
+       java_objectheader *o;
+       va_list            ap;
+       char              *msg;
+    s4                 msglen;
+
+       /* calculate exception message length */
+
+       msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
+
+       va_start(ap, message);
+       msglen += get_variable_message_length(message, ap);
+       va_end(ap);
+
+       /* allocate memory */
+
+       msg = MNEW(char, msglen);
+
+       /* generate message */
 
        utf_sprint_classname(msg, c->name);
-       sprintf(msg + strlen(msg), " (");
+       strcat(msg, " (");
 
        va_start(ap, message);
        vsprintf(msg + strlen(msg), message, ap);
        va_end(ap);
 
-       sprintf(msg + strlen(msg), ")");
+       strcat(msg, ")");
+
+       /* create exception object */
+
+       o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
+                                                         msg);
+
+       /* free memory */
+
+       MFREE(msg, char, msglen);
 
-       return new_exception_message(string_java_lang_UnsupportedClassVersionError,
-                                                                msg);
+       return o;
 }
 
 
@@ -457,31 +544,51 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, char *message,
 
 *******************************************************************************/
 
-java_objectheader *new_verifyerror(methodinfo *m, char *message)
+java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
 {
        java_objectheader *o;
-       char *msg;
-       s4 len;
+       va_list            ap;
+       char              *msg;
+       s4                 msglen;
 
        useinlining = false; /* at least until sure inlining works with exceptions*/
-       len = 8 + utf_strlen(m->class->name) +
-               10 + utf_strlen(m->name) +
-               13 + utf_strlen(m->descriptor) +
-               2 + strlen(message) + 1;
-               
-       msg = MNEW(char, len);
-
-       sprintf(msg, "(class: ");
-       utf_sprint(msg + strlen(msg), m->class->name);
-       sprintf(msg + strlen(msg), ", method: ");
-       utf_sprint(msg + strlen(msg), m->name);
-       sprintf(msg + strlen(msg), ", signature: ");
-       utf_sprint(msg + strlen(msg), m->descriptor);
-       sprintf(msg + strlen(msg), ") %s", 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");
+
+       va_start(ap, message);
+       msglen += get_variable_message_length(message, ap);
+       va_end(ap);
+
+       /* allocate memory */
+
+       msg = MNEW(char, msglen);
+
+       /* 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, ") ");
+
+       va_start(ap, message);
+       vsprintf(msg + strlen(msg), message, ap);
+       va_end(ap);
+
+       /* create exception object */
 
        o = new_exception_message(string_java_lang_VerifyError, msg);
 
-       MFREE(msg, u1, len);
+       /* free memory */
+
+       MFREE(msg, char, msglen);
 
        return o;
 }
@@ -489,11 +596,11 @@ java_objectheader *new_verifyerror(methodinfo *m, char *message)
 
 /* new_arithmeticexception *****************************************************
 
-   generates a java.lang.ArithmeticException for the jit compiler
+   Generates a java.lang.ArithmeticException for the jit compiler.
 
 *******************************************************************************/
 
-java_objectheader *new_arithmeticexception()
+java_objectheader *new_arithmeticexception(void)
 {
        java_objectheader *e;
 
@@ -509,7 +616,8 @@ java_objectheader *new_arithmeticexception()
 
 /* new_arrayindexoutofboundsexception ******************************************
 
-   generates a java.lang.ArrayIndexOutOfBoundsException for the jit compiler
+   Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT
+   compiler.
 
 *******************************************************************************/
 
@@ -531,11 +639,7 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index)
                return *exceptionptr;
 
        s = (java_lang_String *) asm_calljavafunction(m,
-#if POINTERSIZE == 8
-                                                                                                 (void *) (s8) index,
-#else
-                                                                                                 (void *) index,
-#endif
+                                                                                                 (void *) (ptrint) index,
                                                                                                  NULL,
                                                                                                  NULL,
                                                                                                  NULL);
@@ -559,7 +663,7 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index)
 
 *******************************************************************************/
 
-java_objectheader *new_arraystoreexception()
+java_objectheader *new_arraystoreexception(void)
 {
        java_objectheader *e;
 
@@ -578,7 +682,7 @@ java_objectheader *new_arraystoreexception()
 
 *******************************************************************************/
 
-java_objectheader *new_classcastexception()
+java_objectheader *new_classcastexception(void)
 {
        java_objectheader *e;
 
@@ -597,7 +701,7 @@ java_objectheader *new_classcastexception()
 
 *******************************************************************************/
 
-java_objectheader *new_negativearraysizeexception()
+java_objectheader *new_negativearraysizeexception(void)
 {
        java_objectheader *e;
 
@@ -616,7 +720,7 @@ java_objectheader *new_negativearraysizeexception()
 
 *******************************************************************************/
 
-java_objectheader *new_nullpointerexception()
+java_objectheader *new_nullpointerexception(void)
 {
        java_objectheader *e;