X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fexceptions.c;h=6754a62beaa76b2034589bb217a5e32f632b066a;hb=6fd72f4d63f219c79b2132dde9ec0aa5e6c1494b;hp=89ce51c6f97a2e6696f0f8d9ee85f7b22a1ad4e7;hpb=8ab43d6a35711b88122f693e064d3bb61efdc74c;p=cacao.git diff --git a/src/vm/exceptions.c b/src/vm/exceptions.c index 89ce51c6f..6754a62be 100644 --- a/src/vm/exceptions.c +++ b/src/vm/exceptions.c @@ -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, 2007 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. @@ -19,46 +19,61 @@ 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 - - Authors: Christian Thalinger - - Changes: Edwin Steiner - - $Id: exceptions.c 3639 2005-11-08 17:21:37Z twisti $ + $Id: exceptions.c 7596 2007-03-28 21:05:53Z twisti $ */ +#include "config.h" + +#include #include #include #include -#include "config.h" +#include "vm/types.h" + +#include "md-abi.h" #include "mm/memory.h" + +#include "native/jni.h" #include "native/native.h" #include "native/include/java_lang_String.h" #include "native/include/java_lang_Throwable.h" + +#if defined(ENABLE_THREADS) +# include "threads/native/threads.h" +#else +# include "threads/none/threads.h" +#endif + #include "toolbox/logging.h" #include "toolbox/util.h" -#include "vm/class.h" + +#include "vm/builtin.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/vm.h" + #include "vm/jit/asmpart.h" +#include "vm/jit/disass.h" #include "vm/jit/jit.h" +#include "vm/jit/methodheader.h" +#include "vm/jit/stacktrace.h" + +#include "vmcore/class.h" +#include "vmcore/loader.h" +#include "vmcore/options.h" /* for raising exceptions from native methods *********************************/ -#if !defined(USE_THREADS) || !defined(NATIVE_THREADS) +#if !defined(ENABLE_THREADS) java_objectheader *_no_threads_exceptionptr = NULL; #endif @@ -78,21 +93,21 @@ bool exceptions_init(void) !link_class(class_java_lang_Throwable)) return false; - - /* 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 (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) || !link_class(class_java_lang_Error)) return false; +#if defined(ENABLE_JAVASE) + /* java/lang/LinkageError */ + + if (!(class_java_lang_LinkageError = + load_class_bootstrap(utf_java_lang_LinkageError)) || + !link_class(class_java_lang_LinkageError)) + return false; +#endif + /* java/lang/NoClassDefFoundError */ if (!(class_java_lang_NoClassDefFoundError = @@ -100,13 +115,6 @@ bool exceptions_init(void) !link_class(class_java_lang_NoClassDefFoundError)) 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 (!(class_java_lang_OutOfMemoryError = @@ -114,6 +122,13 @@ bool exceptions_init(void) !link_class(class_java_lang_OutOfMemoryError)) return false; + /* java/lang/VirtualMachineError */ + + if (!(class_java_lang_VirtualMachineError = + load_class_bootstrap(utf_java_lang_VirtualMachineError)) || + !link_class(class_java_lang_VirtualMachineError)) + return false; + /* java/lang/Exception */ @@ -122,6 +137,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 = @@ -129,20 +151,6 @@ bool exceptions_init(void) !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 = @@ -151,272 +159,301 @@ bool exceptions_init(void) return false; +#if defined(WITH_CLASSPATH_GNU) + /* java/lang/VMThrowable */ + + if (!(class_java_lang_VMThrowable = + load_class_bootstrap(utf_java_lang_VMThrowable)) || + !link_class(class_java_lang_VMThrowable)) + return false; +#endif + return true; } -static void throw_exception_exit_intern(bool doexit) -{ - java_objectheader *xptr; - classinfo *c; - methodinfo *pss; +/* exceptions_new_class ******************************************************** - xptr = *exceptionptr; + Creates an exception object from the given class and initalizes it. - if (xptr) { - /* clear exception, because we are calling jit code again */ - *exceptionptr = NULL; + IN: + class....class pointer - c = xptr->vftbl->class; +*******************************************************************************/ + +static java_objectheader *exceptions_new_class(classinfo *c) +{ + java_objectheader *o; - pss = class_resolveclassmethod(c, - utf_printStackTrace, - utf_void__void, - class_java_lang_Object, - false); + o = native_new_and_init(c); + + if (o == NULL) + return *exceptionptr; - /* print the stacktrace */ - if (pss) { - asm_calljavafunction(pss, xptr, NULL, NULL, NULL); + return o; +} - /* This normally means, we are EXTREMLY out of memory or have a */ - /* serious problem while printStackTrace. But may be another */ - /* exception, so print it. */ - if (*exceptionptr) { - java_lang_Throwable *t; +/* exceptions_new_utf ********************************************************** - t = (java_lang_Throwable *) *exceptionptr; + Creates an exception object with the given name and initalizes it. - fprintf(stderr, "Exception while printStackTrace(): "); - utf_fprint_classname(stderr, t->header.vftbl->class->name); + IN: + classname....class name in UTF-8 - if (t->detailMessage) { - char *buf; +*******************************************************************************/ - buf = javastring_tochar((java_objectheader *) t->detailMessage); - fprintf(stderr, ": %s", buf); - MFREE(buf, char, strlen(buf)); - } - - fprintf(stderr, "\n"); - } +static java_objectheader *exceptions_new_utf(utf *classname) +{ + classinfo *c; + java_objectheader *o; - } else { - utf_fprint_classname(stderr, c->name); - fprintf(stderr, ": printStackTrace()V not found!\n"); - } + c = load_class_bootstrap(classname); - fflush(stderr); + if (c == NULL) + return *exceptionptr; - /* good bye! */ + o = exceptions_new_class(c); - if (doexit) - exit(1); - } + return o; } -void throw_exception(void) -{ - throw_exception_exit_intern(false); -} +/* exceptions_throw_class ****************************************************** + Creates an exception object from the given class, initalizes and + throws it. -void throw_exception_exit(void) -{ - throw_exception_exit_intern(true); -} + IN: + class....class pointer +*******************************************************************************/ -void throw_main_exception(void) +static void exceptions_throw_class(classinfo *c) { - fprintf(stderr, "Exception in thread \"main\" "); - fflush(stderr); + java_objectheader *o; - throw_exception_exit_intern(false); + o = exceptions_new_class(c); + + if (o == NULL) + return; + + *exceptionptr = o; } -void throw_main_exception_exit(void) -{ - fprintf(stderr, "Exception in thread \"main\" "); - fflush(stderr); +/* exceptions_throw_utf ******************************************************** - throw_exception_exit_intern(true); -} + Creates an exception object with the given name, initalizes and + throws it. + IN: + classname....class name in UTF-8 + +*******************************************************************************/ -void throw_cacao_exception_exit(const char *exception, const char *message, ...) +static void exceptions_throw_utf(utf *classname) { - s4 i; - char *tmp; - s4 len; - va_list ap; + classinfo *c; - len = strlen(exception); - tmp = MNEW(char, len + 1); - strncpy(tmp, exception, len); - tmp[len] = '\0'; + c = load_class_bootstrap(classname); - /* convert to classname */ + if (c == NULL) + return; - for (i = len - 1; i >= 0; i--) - if (tmp[i] == '/') tmp[i] = '.'; + exceptions_throw_class(c); +} - fprintf(stderr, "Exception in thread \"main\" %s", tmp); - MFREE(tmp, char, len); +/* exceptions_throw_utf_throwable ********************************************** - if (strlen(message) > 0) { - fprintf(stderr, ": "); + Creates an exception object with the given name and initalizes it + with the given java/lang/Throwable exception. - va_start(ap, message); - vfprintf(stderr, message, ap); - va_end(ap); - } + IN: + classname....class name in UTF-8 + cause........the given Throwable - fprintf(stderr, "\n"); - fflush(stderr); +*******************************************************************************/ - /* good bye! */ +static void exceptions_throw_utf_throwable(utf *classname, + java_objectheader *cause) +{ + java_objectheader *o; + classinfo *c; + + c = load_class_bootstrap(classname); - exit(1); -} + if (c == NULL) + return; + o = native_new_and_init_throwable(c, cause); -/* exceptions_throw_outofmemory_exit ******************************************* + if (o == NULL) + return; - Just print an: java.lang.InternalError: Out of memory + *exceptionptr = o; +} -*******************************************************************************/ -void exceptions_throw_outofmemory_exit(void) -{ - throw_cacao_exception_exit(string_java_lang_InternalError, - "Out of memory"); -} +/* exceptions_new_utf_javastring *********************************************** + Creates an exception object with the given name and initalizes it + with the given java/lang/String message. -/* new_exception *************************************************************** + IN: + classname....class name in UTF-8 + message......the message as a java.lang.String - Creates an exception object with the given name and initalizes it. + 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) +static java_objectheader *exceptions_new_utf_javastring(utf *classname, + java_objectheader *message) { java_objectheader *o; classinfo *c; + + c = load_class_bootstrap(classname); - if (!(c = load_class_bootstrap(utf_new_char(classname)))) + if (c == NULL) return *exceptionptr; - o = native_new_and_init(c); + o = native_new_and_init_string(c, message); - if (!o) + if (o == NULL) return *exceptionptr; return o; } -/* new_exception_message ******************************************************* +/* exceptions_new_class_utf **************************************************** - Creates an exception object with the given name and initalizes it - with the given char message. + Creates an exception object of the given class and initalizes it. + + IN: + c..........class pointer + message....the message as UTF-8 string *******************************************************************************/ -java_objectheader *new_exception_message(const char *classname, - const char *message) +static java_objectheader *exceptions_new_class_utf(classinfo *c, utf *message) { java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) + java_objectheader *s; + + s = javastring_new(message); + + if (s == NULL) return *exceptionptr; - o = native_new_and_init_string(c, javastring_new_char(message)); + o = native_new_and_init_string(c, s); - if (!o) + if (o == NULL) return *exceptionptr; return o; } -/* new_exception_throwable ***************************************************** +/* exceptions_new_utf_utf ****************************************************** Creates an exception object with the given name and initalizes it - with the given java/lang/Throwable exception. + 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_throwable(const char *classname, - java_lang_Throwable *throwable) +static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message) { - java_objectheader *o; classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + java_objectheader *o; - o = native_new_and_init_throwable(c, throwable); + c = load_class_bootstrap(classname); - if (!o) + if (c == NULL) return *exceptionptr; + o = exceptions_new_class_utf(c, message); + return o; } -/* new_exception_utfmessage **************************************************** +/* new_exception_message ******************************************************* Creates an exception object with the given name and initalizes it - with the given utf message. + 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_utfmessage(const char *classname, utf *message) +static 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_objectheader *s; - o = native_new_and_init_string(c, javastring_new(message)); + s = javastring_new_from_utf_string(message); - if (!o) + if (s == NULL) return *exceptionptr; + o = exceptions_new_utf_javastring(classname, s); + return o; } -/* new_exception_javastring **************************************************** +/* exceptions_throw_class_utf ************************************************** - Creates an exception object with the given name and initalizes it - with the given java/lang/String message. + Creates an exception object of the given class, initalizes and + throws it with the given utf message. + + IN: + c..........class pointer + message....the message as an UTF-8 *******************************************************************************/ -java_objectheader *new_exception_javastring(const char *classname, - java_lang_String *message) +static void exceptions_throw_class_utf(classinfo *c, utf *message) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + *exceptionptr = exceptions_new_class_utf(c, message); +} - o = native_new_and_init_string(c, message); - if (!o) - return *exceptionptr; +/* exceptions_throw_utf_utf **************************************************** - return o; + Creates an exception object with the given name, initalizes and + throws it with the given utf message. + + IN: + classname....class name in UTF-8 + message......the message as an utf * + +*******************************************************************************/ + +static void exceptions_throw_utf_utf(utf *classname, utf *message) +{ + *exceptionptr = exceptions_new_utf_utf(classname, message); } @@ -425,6 +462,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) @@ -444,191 +489,342 @@ java_objectheader *new_exception_int(const char *classname, s4 i) } -/* new_classformaterror ******************************************************** +/* exceptions_new_abstractmethoderror **************************************** - generates a java.lang.ClassFormatError for the classloader + Generates a java.lang.AbstractMethodError for the VM. *******************************************************************************/ -java_objectheader *new_classformaterror(classinfo *c, const char *message, ...) +java_objectheader *exceptions_new_abstractmethoderror(void) { java_objectheader *o; - char *msg; - s4 msglen; - va_list ap; - /* calculate message length */ + o = exceptions_new_utf(utf_java_lang_AbstractMethodError); - msglen = 0; + return o; +} - if (c) - msglen += utf_strlen(c->name) + strlen(" ("); - va_start(ap, message); - msglen += get_variable_message_length(message, ap); - va_end(ap); +/* exceptions_new_error ******************************************************** - if (c) - msglen += strlen(")"); + Generates a java.lang.Error for the VM. - msglen += strlen("0"); +*******************************************************************************/ - /* allocate a buffer */ +#if defined(ENABLE_JAVAME_CLDC1_1) +static java_objectheader *exceptions_new_error(utf *message) +{ + java_objectheader *o; - msg = MNEW(char, msglen); + o = exceptions_new_class_utf(class_java_lang_Error, message); - /* print message into allocated buffer */ + return o; +} +#endif - if (c) { - utf_sprint_classname(msg, c->name); - strcat(msg, " ("); - } - va_start(ap, message); - vsprintf(msg + strlen(msg), message, ap); - va_end(ap); +/* exceptions_asm_new_abstractmethoderror ************************************** - if (c) - strcat(msg, ")"); + Generates a java.lang.AbstractMethodError for + asm_abstractmethoderror. - o = new_exception_message(string_java_lang_ClassFormatError, msg); +*******************************************************************************/ - MFREE(msg, char, msglen); +java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra) +{ + stackframeinfo sfi; + java_objectheader *e; - return o; + /* create the stackframeinfo (XPC is equal to RA) */ + + stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra); + + /* create the exception */ + +#if defined(ENABLE_JAVASE) + e = exceptions_new_abstractmethoderror(); +#else + e = exceptions_new_error(utf_java_lang_AbstractMethodError); +#endif + + /* remove the stackframeinfo */ + + stacktrace_remove_stackframeinfo(&sfi); + + return e; } -/* new_classnotfoundexception ************************************************** +/* exceptions_new_arraystoreexception ****************************************** - Generates a java.lang.ClassNotFoundException for the classloader. + Generates a java.lang.ArrayStoreException for the VM. *******************************************************************************/ -java_objectheader *new_classnotfoundexception(utf *name) +java_objectheader *exceptions_new_arraystoreexception(void) { java_objectheader *o; - o = native_new_and_init_string(class_java_lang_ClassNotFoundException, - javastring_new(name)); - - if (!o) - return *exceptionptr; + o = exceptions_new_utf(utf_java_lang_ArrayStoreException); return o; } -/* new_noclassdeffounderror **************************************************** +/* exceptions_throw_abstractmethoderror **************************************** - Generates a java.lang.NoClassDefFoundError + Generates and throws a java.lang.AbstractMethodError for the VM. *******************************************************************************/ -java_objectheader *new_noclassdeffounderror(utf *name) +void exceptions_throw_abstractmethoderror(void) { - java_objectheader *o; - - o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, - javastring_new(name)); - - if (!o) - return *exceptionptr; - - return o; + exceptions_throw_utf(utf_java_lang_AbstractMethodError); } -/* classnotfoundexception_to_noclassdeffounderror ****************************** +/* exceptions_throw_classcircularityerror ************************************** - Check the *exceptionptr for a ClassNotFoundException. If it is one, - convert it to a NoClassDefFoundError. + Generates and throws a java.lang.ClassCircularityError for the + classloader. + + IN: + c............the class in which the error was found *******************************************************************************/ -void classnotfoundexception_to_noclassdeffounderror(void) +void exceptions_throw_classcircularityerror(classinfo *c) { - java_objectheader *xptr; - java_objectheader *cause; - - /* get the cause */ + java_objectheader *o; + char *msg; + s4 msglen; - cause = *exceptionptr; + /* calculate message length */ - /* convert ClassNotFoundException's to NoClassDefFoundError's */ + msglen = utf_bytes(c->name) + strlen("0"); - if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) { - /* clear exception, because we are calling jit code again */ + /* allocate a buffer */ - *exceptionptr = NULL; + msg = MNEW(char, msglen); - /* create new error */ + /* print message into allocated buffer */ - xptr = - new_exception_javastring(string_java_lang_NoClassDefFoundError, - ((java_lang_Throwable *) cause)->detailMessage); + utf_copy_classname(msg, c->name); - /* we had an exception while creating the error */ + o = new_exception_message(utf_java_lang_ClassCircularityError, msg); - if (*exceptionptr) - return; + MFREE(msg, char, msglen); - /* set new exception */ + if (o == NULL) + return; - *exceptionptr = xptr; - } + *exceptionptr = o; } -/* new_internalerror *********************************************************** +/* exceptions_throw_classformaterror ******************************************* - Generates a java.lang.InternalError for the VM. + Generates and throws a java.lang.ClassFormatError for the VM. + + IN: + c............the class in which the error was found + message......UTF-8 format string *******************************************************************************/ -java_objectheader *new_internalerror(const char *message, ...) +void exceptions_throw_classformaterror(classinfo *c, const char *message, ...) { java_objectheader *o; - va_list ap; char *msg; s4 msglen; + va_list ap; - /* calculate exception message length */ + /* calculate message length */ + + msglen = 0; + + if (c != NULL) + msglen += utf_bytes(c->name) + strlen(" ("); va_start(ap, message); - msglen = get_variable_message_length(message, ap); + msglen += get_variable_message_length(message, ap); va_end(ap); - /* allocate memory */ + if (c != NULL) + msglen += strlen(")"); + + msglen += strlen("0"); + + /* allocate a buffer */ msg = MNEW(char, msglen); - /* generate message */ + /* print message into allocated buffer */ + + if (c != NULL) { + utf_copy_classname(msg, c->name); + strcat(msg, " ("); + } va_start(ap, message); - vsprintf(msg, message, ap); + vsprintf(msg + strlen(msg), message, ap); va_end(ap); - /* create exception object */ + if (c != NULL) + strcat(msg, ")"); - o = new_exception_message(string_java_lang_InternalError, msg); + o = new_exception_message(utf_java_lang_ClassFormatError, msg); - /* free memory */ + MFREE(msg, char, msglen); + + *exceptionptr = o; +} + + +/* exceptions_throw_classnotfoundexception ************************************* + + Generates and throws a java.lang.ClassNotFoundException for the + VM. + + IN: + name.........name of the class not found as a utf * + +*******************************************************************************/ + +void exceptions_throw_classnotfoundexception(utf *name) +{ + /* we use class here, as this one is rather frequent */ + + exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name); +} + + +/* exceptions_throw_noclassdeffounderror *************************************** + + Generates and throws a java.lang.NoClassDefFoundError. + + IN: + name.........name of the class not found as a utf * + +*******************************************************************************/ + +void exceptions_throw_noclassdeffounderror(utf *name) +{ + if (vm_initializing) + vm_abort("java.lang.NoClassDefFoundError: %s", name->text); + + exceptions_throw_class_utf(class_java_lang_NoClassDefFoundError, name); +} + + +/* exceptions_throw_noclassdeffounderror_wrong_name **************************** + + Generates and throws a java.lang.NoClassDefFoundError with a + specific message: + + + + IN: + name.........name of the class not found as a utf * + +*******************************************************************************/ + +void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name) +{ + char *msg; + s4 msglen; + utf *u; + + msglen = utf_bytes(c->name) + strlen(" (wrong name: ") + + utf_bytes(name) + strlen(")") + strlen("0"); + + msg = MNEW(char, msglen); + + utf_copy_classname(msg, c->name); + strcat(msg, " (wrong name: "); + utf_cat_classname(msg, name); + strcat(msg, ")"); + + u = utf_new_char(msg); MFREE(msg, char, msglen); - return o; + exceptions_throw_noclassdeffounderror(u); +} + + +/* 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; + java_lang_Throwable *t; + java_lang_String *s; + + /* 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 */ + + t = (java_lang_Throwable *) cause; + s = t->detailMessage; + + xptr = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError, s); + + /* we had an exception while creating the error */ + + if (*exceptionptr) + return; + + /* set new exception */ + + *exceptionptr = xptr; + } +} + + +/* exceptions_throw_exceptionininitializererror ******************************** + + Generates and throws a java.lang.ExceptionInInitializerError for + the VM. + + IN: + cause......cause exception object + +*******************************************************************************/ + +void exceptions_throw_exceptionininitializererror(java_objectheader *cause) +{ + exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError, + cause); } -/* exceptions_new_nosuchmethoderror ******************************************** +/* exceptions_throw_incompatibleclasschangeerror ******************************* - Generates a java.lang.NoSuchMethodError with an error message. + Generates and throws a java.lang.IncompatibleClassChangeError for + the VM. + + IN: + message......UTF-8 message format string *******************************************************************************/ -java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c, - utf *name, utf *desc) +void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message) { java_objectheader *o; char *msg; @@ -636,50 +832,61 @@ 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(message) + 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); + utf_copy_classname(msg, c->name); + strcat(msg, message); - o = native_new_and_init_string(class_java_lang_NoSuchMethodError, - javastring_new_char(msg)); + o = native_new_and_init_string(utf_java_lang_IncompatibleClassChangeError, + javastring_new_from_utf_string(msg)); /* free memory */ MFREE(msg, char, msglen); - return o; + if (o == NULL) + return; + + *exceptionptr = o; +} + + +/* exceptions_throw_instantiationerror ***************************************** + + Generates and throws a java.lang.InstantiationError for the VM. + +*******************************************************************************/ + +void exceptions_throw_instantiationerror(classinfo *c) +{ + exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name); } -/* new_unsupportedclassversionerror ******************************************** +/* exceptions_throw_internalerror ********************************************** - generates a java.lang.UnsupportedClassVersionError for the classloader + Generates and throws a java.lang.InternalError for the VM. + + IN: + message......UTF-8 message format string *******************************************************************************/ -java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...) +void exceptions_throw_internalerror(const char *message, ...) { java_objectheader *o; va_list ap; char *msg; - s4 msglen; + 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); + msglen = get_variable_message_length(message, ap); va_end(ap); /* allocate memory */ @@ -688,261 +895,1147 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me /* generate message */ - utf_sprint_classname(msg, c->name); - strcat(msg, " ("); - va_start(ap, message); - vsprintf(msg + strlen(msg), message, ap); + vsprintf(msg, message, ap); va_end(ap); - strcat(msg, ")"); - /* create exception object */ - o = new_exception_message(string_java_lang_UnsupportedClassVersionError, - msg); + o = new_exception_message(utf_java_lang_InternalError, msg); /* free memory */ MFREE(msg, char, msglen); - return o; + if (o == NULL) + return; + + *exceptionptr = o; } -/* new_verifyerror ************************************************************* +/* exceptions_throw_linkageerror *********************************************** + + Generates and throws java.lang.LinkageError with an error message. - generates a java.lang.VerifyError for the jit compiler + 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. *******************************************************************************/ -java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) +void exceptions_throw_linkageerror(const char *message, classinfo *c) { java_objectheader *o; - va_list ap; char *msg; s4 msglen; - useinlining = false; /* at least until sure inlining works with exceptions*/ - /* calculate exception message length */ - 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); - va_end(ap); + msglen = strlen(message) + 1; + if (c != NULL) + msglen += utf_bytes(c->name); + /* allocate memory */ msg = MNEW(char, msglen); /* generate message */ - 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); - va_end(ap); + strcpy(msg,message); - /* create exception object */ + if (c != NULL) + utf_cat_classname(msg, c->name); - o = new_exception_message(string_java_lang_VerifyError, msg); + o = native_new_and_init_string(class_java_lang_LinkageError, + javastring_new_from_utf_string(msg)); /* free memory */ MFREE(msg, char, msglen); - return o; + if (o == NULL) + return; + + *exceptionptr = o; } -/* new_arithmeticexception ***************************************************** +/* exceptions_throw_nosuchfielderror ******************************************* + + Generates and throws a java.lang.NoSuchFieldError with an error + message. - Generates a java.lang.ArithmeticException for the jit compiler. + IN: + c............class in which the field was not found + name.........name of the field *******************************************************************************/ -java_objectheader *new_arithmeticexception(void) +void exceptions_throw_nosuchfielderror(classinfo *c, utf *name) { - java_objectheader *e; + char *msg; + s4 msglen; + utf *u; - e = new_exception_message(string_java_lang_ArithmeticException, - string_java_lang_ArithmeticException_message); + /* calculate exception message length */ - if (!e) - return *exceptionptr; + msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0"); - return e; -} + /* allocate memory */ + msg = MNEW(char, msglen); -/* new_arrayindexoutofboundsexception ****************************************** + /* generate message */ - Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT - compiler. + utf_copy_classname(msg, c->name); + strcat(msg, "."); + utf_cat(msg, name); -*******************************************************************************/ + u = utf_new_char(msg); -java_objectheader *new_arrayindexoutofboundsexception(s4 index) -{ - java_objectheader *e; - methodinfo *m; - java_lang_String *s; + /* free memory */ - /* convert the index into a String, like Sun does */ + MFREE(msg, char, msglen); - m = class_resolveclassmethod(class_java_lang_String, - utf_new_char("valueOf"), - utf_new_char("(I)Ljava/lang/String;"), - class_java_lang_Object, - true); + exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u); +} - if (!m) - return *exceptionptr; - s = (java_lang_String *) asm_calljavafunction(m, - (void *) (ptrint) index, - NULL, - NULL, - NULL); +/* exceptions_throw_nosuchmethoderror ****************************************** - if (!s) - return *exceptionptr; + Generates and throws a java.lang.NoSuchMethodError with an error + message. - e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException, - s); + IN: + c............class in which the method was not found + name.........name of the method + desc.........descriptor of the method - if (!e) - return *exceptionptr; +*******************************************************************************/ - return e; -} +void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc) +{ + char *msg; + s4 msglen; + utf *u; + /* calculate exception message length */ -/* new_arraystoreexception ***************************************************** + msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + + utf_bytes(desc) + strlen("0"); - generates a java.lang.ArrayStoreException for the jit compiler + /* allocate memory */ -*******************************************************************************/ + msg = MNEW(char, msglen); -java_objectheader *new_arraystoreexception(void) -{ - java_objectheader *e; + /* generate message */ - e = new_exception(string_java_lang_ArrayStoreException); -/* e = native_new_and_init(class_java_lang_ArrayStoreException); */ + utf_copy_classname(msg, c->name); + strcat(msg, "."); + utf_cat(msg, name); + utf_cat(msg, desc); - if (!e) - return *exceptionptr; + u = utf_new_char(msg); - return e; + /* free memory */ + + MFREE(msg, char, msglen); + + exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u); } -/* new_classcastexception ****************************************************** +/* exceptions_throw_outofmemoryerror ******************************************* - generates a java.lang.ClassCastException for the jit compiler + Generates and throws an java.lang.OutOfMemoryError for the VM. *******************************************************************************/ -java_objectheader *new_classcastexception(void) +void exceptions_throw_outofmemoryerror(void) { - java_objectheader *e; - - e = new_exception(string_java_lang_ClassCastException); - - if (!e) - return *exceptionptr; - - return e; + exceptions_throw_class(class_java_lang_OutOfMemoryError); } -/* new_illegalargumentexception ************************************************ +/* exceptions_throw_unsatisfiedlinkerror *************************************** + + Generates and throws a java.lang.UnsatisfiedLinkError for the + classloader. - Generates a java.lang.IllegalArgumentException for the VM system. + IN: + name......UTF-8 name string *******************************************************************************/ -java_objectheader *new_illegalargumentexception(void) +void exceptions_throw_unsatisfiedlinkerror(utf *name) { - java_objectheader *e; - - if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException))) - return *exceptionptr; - - return e; +#if defined(ENABLE_JAVASE) + exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name); +#else + exceptions_throw_class_utf(class_java_lang_Error, name); +#endif } -/* new_illegalmonitorstateexception ******************************************** +/* exceptions_throw_unsupportedclassversionerror ******************************* - Generates a java.lang.IllegalMonitorStateException for the VM - thread system. + Generates and throws a java.lang.UnsupportedClassVersionError for + the classloader. + + IN: + c............class in which the method was not found + message......UTF-8 format string *******************************************************************************/ -java_objectheader *new_illegalmonitorstateexception(void) +void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi) { - java_objectheader *e; + java_objectheader *o; + char *msg; + s4 msglen; - if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException))) - return *exceptionptr; + /* calculate exception message length */ - return e; -} + msglen = + utf_bytes(c->name) + + strlen(" (Unsupported major.minor version 00.0)") + + strlen("0"); + /* allocate memory */ -/* new_negativearraysizeexception ********************************************** + msg = MNEW(char, msglen); - generates a java.lang.NegativeArraySizeException for the jit compiler + /* generate message */ -*******************************************************************************/ + utf_copy_classname(msg, c->name); + sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)", + ma, mi); -java_objectheader *new_negativearraysizeexception(void) -{ - java_objectheader *e; + /* create exception object */ - e = new_exception(string_java_lang_NegativeArraySizeException); + o = new_exception_message(utf_java_lang_UnsupportedClassVersionError, msg); - if (!e) - return *exceptionptr; + /* free memory */ - return e; + MFREE(msg, char, msglen); + + if (o == NULL) + return; + + *exceptionptr = o; } -/* new_nullpointerexception **************************************************** +/* exceptions_throw_verifyerror ************************************************ - generates a java.lang.NullPointerException for the jit compiler + Generates and throws a java.lang.VerifyError for the JIT compiler. + + IN: + m............method in which the error was found + message......UTF-8 format string *******************************************************************************/ -java_objectheader *new_nullpointerexception(void) +void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...) { - java_objectheader *e; + java_objectheader *o; + va_list ap; + char *msg; + s4 msglen; - e = native_new_and_init(class_java_lang_NullPointerException); + /* calculate exception message length */ - if (!e) - return *exceptionptr; + msglen = 0; - return e; + if (m != NULL) + 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); + msglen += get_variable_message_length(message, ap); + va_end(ap); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + if (m != NULL) { + 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, ") "); + } + + va_start(ap, message); + vsprintf(msg + strlen(msg), message, ap); + va_end(ap); + + /* create exception object */ + + o = new_exception_message(utf_java_lang_VerifyError, msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + *exceptionptr = o; +} + + +/* 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 = ""; assert(0); break; + } + strcat(msg, typename); + strcat(msg, " on stack"); + + /* create exception object */ + + o = new_exception_message(utf_java_lang_VerifyError, msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + *exceptionptr = o; +} + + +/* exceptions_new_arithmeticexception ****************************************** + + Generates a java.lang.ArithmeticException for the JIT compiler. + +*******************************************************************************/ + +java_objectheader *exceptions_new_arithmeticexception(void) +{ + java_objectheader *o; + + o = new_exception_message(utf_java_lang_ArithmeticException, "/ by zero"); + + if (o == NULL) + return *exceptionptr; + + return o; +} + + +/* exceptions_new_arrayindexoutofboundsexception ******************************* + + Generates a java.lang.ArrayIndexOutOfBoundsException for the VM + system. + +*******************************************************************************/ + +java_objectheader *exceptions_new_arrayindexoutofboundsexception(s4 index) +{ + java_objectheader *o; + methodinfo *m; + java_objectheader *s; + + /* convert the index into a String, like Sun does */ + + m = class_resolveclassmethod(class_java_lang_String, + utf_new_char("valueOf"), + utf_new_char("(I)Ljava/lang/String;"), + class_java_lang_Object, + true); + + if (m == NULL) + return *exceptionptr; + + s = vm_call_method(m, NULL, index); + + if (s == NULL) + return *exceptionptr; + + o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException, + s); + + if (o == NULL) + return *exceptionptr; + + return o; +} + + +/* exceptions_throw_arrayindexoutofboundsexception ***************************** + + Generates and throws a java.lang.ArrayIndexOutOfBoundsException for + the VM. + +*******************************************************************************/ + +void exceptions_throw_arrayindexoutofboundsexception(void) +{ + exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException); +} + + +/* exceptions_throw_arraystoreexception **************************************** + + Generates and throws a java.lang.ArrayStoreException for the VM. + +*******************************************************************************/ + +void exceptions_throw_arraystoreexception(void) +{ + exceptions_throw_utf(utf_java_lang_ArrayStoreException); +/* e = native_new_and_init(class_java_lang_ArrayStoreException); */ +} + + +/* exceptions_new_classcastexception ******************************************* + + Generates a java.lang.ClassCastException for the JIT compiler. + +*******************************************************************************/ + +java_objectheader *exceptions_new_classcastexception(java_objectheader *o) +{ + java_objectheader *e; + utf *classname; + java_lang_String *s; + + classname = o->vftbl->class->name; + + s = javastring_new(classname); + + e = native_new_and_init_string(class_java_lang_ClassCastException, s); + + if (e == NULL) + return *exceptionptr; + + return e; +} + + +/* exceptions_throw_clonenotsupportedexception ********************************* + + Generates and throws a java.lang.CloneNotSupportedException for the + VM. + +*******************************************************************************/ + +void exceptions_throw_clonenotsupportedexception(void) +{ + exceptions_throw_utf(utf_java_lang_CloneNotSupportedException); +} + + +/* exceptions_throw_illegalaccessexception ************************************* + + Generates and throws a java.lang.IllegalAccessException for the VM. + +*******************************************************************************/ + +void exceptions_throw_illegalaccessexception(classinfo *c) +{ + /* XXX handle argument */ + + exceptions_throw_utf(utf_java_lang_IllegalAccessException); +} + + +/* exceptions_throw_illegalargumentexception *********************************** + + Generates and throws a java.lang.IllegalArgumentException for the + VM. + +*******************************************************************************/ + +void exceptions_throw_illegalargumentexception(void) +{ + exceptions_throw_utf(utf_java_lang_IllegalArgumentException); +} + + +/* exceptions_throw_illegalmonitorstateexception ******************************* + + Generates and throws a java.lang.IllegalMonitorStateException for + the VM. + +*******************************************************************************/ + +void exceptions_throw_illegalmonitorstateexception(void) +{ + exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException); +} + + +/* exceptions_throw_instantiationexception ************************************* + + Generates and throws a java.lang.InstantiationException for the VM. + +*******************************************************************************/ + +void exceptions_throw_instantiationexception(classinfo *c) +{ + exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name); +} + + +/* exceptions_throw_interruptedexception *************************************** + + Generates and throws a java.lang.InterruptedException for the VM. + +*******************************************************************************/ + +void exceptions_throw_interruptedexception(void) +{ + exceptions_throw_utf(utf_java_lang_InterruptedException); +} + + +/* exceptions_throw_invocationtargetexception ********************************** + + Generates and throws a java.lang.reflect.InvocationTargetException + for the VM. + + IN: + cause......cause exception object + +*******************************************************************************/ + +void exceptions_throw_invocationtargetexception(java_objectheader *cause) +{ + exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException, + cause); +} + + +/* exceptions_throw_negativearraysizeexception ********************************* + + Generates and throws a java.lang.NegativeArraySizeException for the + VM. + +*******************************************************************************/ + +void exceptions_throw_negativearraysizeexception(void) +{ + exceptions_throw_utf(utf_java_lang_NegativeArraySizeException); +} + + +/* exceptions_new_nullpointerexception ***************************************** + + Generates a java.lang.NullPointerException for the VM system. + +*******************************************************************************/ + +java_objectheader *exceptions_new_nullpointerexception(void) +{ + java_objectheader *o; + + o = exceptions_new_class(class_java_lang_NullPointerException); + + return o; +} + + +/* exceptions_throw_nullpointerexception *************************************** + + Generates a java.lang.NullPointerException for the VM system and + throw it in the VM system. + +*******************************************************************************/ + +void exceptions_throw_nullpointerexception(void) +{ + exceptions_throw_class(class_java_lang_NullPointerException); +} + + +/* exceptions_throw_stringindexoutofboundsexception **************************** + + Generates and throws a java.lang.StringIndexOutOfBoundsException + for the VM. + +*******************************************************************************/ + +void exceptions_throw_stringindexoutofboundsexception(void) +{ + exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException); +} + + +/* exceptions_get_exception **************************************************** + + Returns the current exception pointer of the current thread. + +*******************************************************************************/ + +java_objectheader *exceptions_get_exception(void) +{ + /* return the exception */ + + return *exceptionptr; +} + + +/* exceptions_set_exception **************************************************** + + Sets the exception pointer of the current thread. + +*******************************************************************************/ + +void exceptions_set_exception(java_objectheader *o) +{ + /* set the exception */ + + *exceptionptr = o; +} + + +/* exceptions_clear_exception ************************************************** + + Clears the current exception pointer of the current thread. + +*******************************************************************************/ + +void exceptions_clear_exception(void) +{ + /* and clear the exception */ + + *exceptionptr = NULL; +} + + +/* exceptions_fillinstacktrace ************************************************* + + Calls the fillInStackTrace-method of the currently thrown + exception. + +*******************************************************************************/ + +java_objectheader *exceptions_fillinstacktrace(void) +{ + java_objectheader *e; + methodinfo *m; + + /* get exception */ + + e = *exceptionptr; + assert(e); + + /* clear exception */ + + *exceptionptr = NULL; + + /* resolve methodinfo pointer from exception object */ + + m = class_resolvemethod(e->vftbl->class, + utf_fillInStackTrace, + utf_void__java_lang_Throwable); + + /* call function */ + + (void) vm_call_method(m, e); + + /* return exception object */ + + return e; +} + + +/* 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_new_hardware_exception ******************************************* + + Creates the correct exception for a hardware-exception thrown and + caught by a signal handler. + +*******************************************************************************/ + +java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val) +{ + stackframeinfo sfi; + java_objectheader *e; + java_objectheader *o; + s4 index; + + /* create stackframeinfo */ + + stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc); + + switch (type) { + case EXCEPTION_HARDWARE_NULLPOINTER: + e = exceptions_new_nullpointerexception(); + break; + + case EXCEPTION_HARDWARE_ARITHMETIC: + e = exceptions_new_arithmeticexception(); + break; + + case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS: + index = (s4) val; + e = exceptions_new_arrayindexoutofboundsexception(index); + break; + + case EXCEPTION_HARDWARE_CLASSCAST: + o = (java_objectheader *) val; + e = exceptions_new_classcastexception(o); + break; + + case EXCEPTION_HARDWARE_EXCEPTION: + e = exceptions_fillinstacktrace(); + break; + + default: + /* let's try to get a backtrace */ + + codegen_get_pv_from_pc(xpc); + + /* if that does not work, print more debug info */ + + log_println("exceptions_new_hardware_exception: unknown exception type %d", type); + +#if SIZEOF_VOID_P == 8 + log_println("PC=0x%016lx", xpc); +#else + log_println("PC=0x%08x", xpc); +#endif + +#if defined(ENABLE_DISASSEMBLER) + log_println("machine instruction at PC:"); + disassinstr(xpc); +#endif + + vm_abort("Exiting..."); + } + + /* remove stackframeinfo */ + + stacktrace_remove_stackframeinfo(&sfi); + + /* return the exception object */ + + return e; +} + + +/* exceptions_handle_exception ************************************************* + + 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; + codeinfo *code; + s4 issync; + dseg_exception_entry *ex; + s4 exceptiontablelength; + s4 i; + classref_or_classinfo cr; + classinfo *c; +#if defined(ENABLE_THREADS) + java_objectheader *o; +#endif + +#ifdef __S390__ + /* Addresses are 31 bit integers */ +# define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF) +#else +# define ADDR_MASK(x) (x) +#endif + + xpc = ADDR_MASK(xpc); + + /* get info from the method header */ + + code = *((codeinfo **) (pv + CodeinfoPointer)); + issync = *((s4 *) (pv + IsSync)); + ex = (dseg_exception_entry *) (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); +#endif + + for (i = 0; i < exceptiontablelength; i++) { + /* ATTENTION: keep this here, as we need to decrement the + pointer before the loop executes! */ + + 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 ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) { + cr = ex->catchtype; + + /* NULL catches everything */ + + 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; + } + + /* is the thrown exception an instance of the catch class? */ + + 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(ENABLE_THREADS) + /* is this method synchronized? */ + + if (issync) { + /* get synchronization object */ + +# if defined(__MIPS__) && (SIZEOF_VOID_P == 4) + /* XXX change this if we ever want to use 4-byte stackslots */ + o = *((java_objectheader **) (sp + issync - 8)); +# else + o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P)); +#endif + + assert(o != NULL); + + lock_monitor_exit(o); + } +#endif + + /* none of the exceptions catch this one */ + + return NULL; +} +#endif /* defined(ENABLE_JIT) */ + + +/* 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; +#if defined(ENABLE_JAVASE) + java_lang_Throwable *cause; +#endif + utf *u; + + t = (java_lang_Throwable *) xptr; + + if (t == NULL) { + puts("NULL\n"); + return; + } + +#if defined(ENABLE_JAVASE) + cause = t->cause; +#endif + + /* print the root exception */ + + utf_display_printable_ascii_classname(t->header.vftbl->class->name); + + if (t->detailMessage != NULL) { + u = javastring_toutf(t->detailMessage, false); + + printf(": "); + utf_display_printable_ascii(u); + } + + putc('\n', stdout); + +#if defined(ENABLE_JAVASE) + /* print the cause if available */ + + if ((cause != NULL) && (cause != t)) { + printf("Caused by: "); + utf_display_printable_ascii_classname(cause->header.vftbl->class->name); + + if (cause->detailMessage) { + u = javastring_toutf(cause->detailMessage, false); + + printf(": "); + utf_display_printable_ascii(u); + } + + putc('\n', stdout); + } +#endif +} + + +/* exceptions_print_current_exception ****************************************** + + Prints the current pending exception, the detail message and the + cause, if available, with CACAO internal functions to stdout. + +*******************************************************************************/ + +void exceptions_print_current_exception(void) +{ + java_objectheader *xptr; + + xptr = *exceptionptr; + + exceptions_print_exception(xptr); +} + + +/* exceptions_print_stacktrace ************************************************* + + Prints a pending exception with Throwable.printStackTrace(). If + there happens an exception during printStackTrace(), we print the + thrown exception and the original one. + + NOTE: This function calls Java code. + +*******************************************************************************/ + +void exceptions_print_stacktrace(void) +{ + java_objectheader *oxptr; + java_objectheader *xptr; + classinfo *c; + methodinfo *m; + + /* get original exception */ + + oxptr = *exceptionptr; + + if (oxptr == NULL) + vm_abort("exceptions_print_stacktrace: no exception thrown"); + + /* clear exception, because we are calling jit code again */ + + *exceptionptr = NULL; + + c = oxptr->vftbl->class; + + /* find the printStackTrace() method */ + + m = class_resolveclassmethod(c, + utf_printStackTrace, + utf_void__void, + class_java_lang_Object, + false); + + if (m == NULL) + vm_abort("exceptions_print_stacktrace: printStackTrace()V not found"); + + /* print compatibility message */ + + fprintf(stderr, "Exception in thread \"main\" "); + + /* print the stacktrace */ + + (void) vm_call_method(m, oxptr); + + /* This normally means, we are EXTREMLY out of memory or + have a serious problem while printStackTrace. But may + be another exception, so print it. */ + + xptr = *exceptionptr; + + if (xptr != NULL) { + fprintf(stderr, "Exception while printStackTrace(): "); + + /* now print original exception */ + + exceptions_print_exception(xptr); + stacktrace_print_trace(xptr); + + /* now print original exception */ + + fprintf(stderr, "Original exception was: "); + exceptions_print_exception(oxptr); + stacktrace_print_trace(oxptr); + } + + fflush(stderr); } @@ -957,4 +2050,5 @@ java_objectheader *new_nullpointerexception(void) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */