X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fexceptions.c;h=fdf447892942ebe0a280282ed9dd7715bcf35d57;hb=4f7f3896b97b7c228687fc2f4f04fcca7cf8f67f;hp=4e97a598b5644e427225db83483fa3277c606709;hpb=d66d2d66ee7b7082be9f0754d7312629bbd391af;p=cacao.git diff --git a/src/vm/exceptions.c b/src/vm/exceptions.c index 4e97a598b..fdf447892 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 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,16 +19,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at + Contact: cacao@cacaojvm.org Authors: Christian Thalinger Changes: Edwin Steiner - $Id: exceptions.c 3893 2005-12-06 20:18:01Z twisti $ + $Id: exceptions.c 5935 2006-11-08 20:27:37Z twisti $ */ @@ -54,6 +54,7 @@ #include "vm/loader.h" #include "vm/options.h" #include "vm/stringlocal.h" +#include "vm/vm.h" #include "vm/jit/asmpart.h" #include "vm/jit/jit.h" #include "vm/jit/methodheader.h" @@ -61,7 +62,7 @@ /* for raising exceptions from native methods *********************************/ -#if !defined(USE_THREADS) || !defined(NATIVE_THREADS) +#if !defined(ENABLE_THREADS) java_objectheader *_no_threads_exceptionptr = NULL; #endif @@ -96,11 +97,11 @@ bool exceptions_init(void) !link_class(class_java_lang_Error)) return false; - /* java/lang/NoClassDefFoundError */ + /* java/lang/AbstractMethodError */ - if (!(class_java_lang_NoClassDefFoundError = - load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) || - !link_class(class_java_lang_NoClassDefFoundError)) + if (!(class_java_lang_AbstractMethodError = + load_class_bootstrap(utf_java_lang_AbstractMethodError)) || + !link_class(class_java_lang_AbstractMethodError)) return false; /* java/lang/LinkageError */ @@ -110,6 +111,13 @@ bool exceptions_init(void) !link_class(class_java_lang_LinkageError)) return false; + /* java/lang/NoClassDefFoundError */ + + if (!(class_java_lang_NoClassDefFoundError = + load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) || + !link_class(class_java_lang_NoClassDefFoundError)) + return false; + /* java/lang/NoSuchMethodError */ if (!(class_java_lang_NoSuchMethodError = @@ -132,6 +140,13 @@ bool exceptions_init(void) !link_class(class_java_lang_Exception)) return false; + /* java/lang/ClassCastException */ + + if (!(class_java_lang_ClassCastException = + load_class_bootstrap(utf_java_lang_ClassCastException)) || + !link_class(class_java_lang_ClassCastException)) + return false; + /* java/lang/ClassNotFoundException */ if (!(class_java_lang_ClassNotFoundException = @@ -186,8 +201,9 @@ static void throw_exception_exit_intern(bool doexit) false); /* print the stacktrace */ + if (pss) { - asm_calljavafunction(pss, xptr, NULL, NULL, NULL); + (void) vm_call_method(pss, xptr); /* This normally means, we are EXTREMLY out of memory or have a */ /* serious problem while printStackTrace. But may be another */ @@ -199,7 +215,7 @@ static void throw_exception_exit_intern(bool doexit) t = (java_lang_Throwable *) *exceptionptr; fprintf(stderr, "Exception while printStackTrace(): "); - utf_fprint_classname(stderr, t->header.vftbl->class->name); + utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name); if (t->detailMessage) { char *buf; @@ -213,7 +229,7 @@ static void throw_exception_exit_intern(bool doexit) } } else { - utf_fprint_classname(stderr, c->name); + utf_fprint_printable_ascii_classname(stderr, c->name); fprintf(stderr, ": printStackTrace()V not found!\n"); } @@ -312,6 +328,13 @@ void exceptions_throw_outofmemory_exit(void) Creates an exception object with the given name and initalizes it. + IN: + classname....class name in UTF-8 + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_exception(const char *classname) @@ -336,23 +359,26 @@ java_objectheader *new_exception(const char *classname) Creates an exception object with the given name and initalizes it with the given char message. + IN: + classname....class name in UTF-8 + message......message in UTF-8 + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_exception_message(const char *classname, const char *message) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; - - o = native_new_and_init_string(c, javastring_new_char(message)); + java_lang_String *s; - if (!o) + s = javastring_new_from_utf_string(message); + if (!s) return *exceptionptr; - return o; + return new_exception_javastring(classname, s); } @@ -361,6 +387,14 @@ java_objectheader *new_exception_message(const char *classname, Creates an exception object with the given name and initalizes it with the given java/lang/Throwable exception. + IN: + classname....class name in UTF-8 + throwable....the given Throwable + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_exception_throwable(const char *classname, @@ -386,22 +420,25 @@ java_objectheader *new_exception_throwable(const char *classname, Creates an exception object with the given name and initalizes it with the given utf message. + IN: + classname....class name in UTF-8 + message......the message as an utf * + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_exception_utfmessage(const char *classname, utf *message) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; - - o = native_new_and_init_string(c, javastring_new(message)); + java_lang_String *s; - if (!o) + s = javastring_new(message); + if (!s) return *exceptionptr; - return o; + return new_exception_javastring(classname, s); } @@ -410,6 +447,14 @@ java_objectheader *new_exception_utfmessage(const char *classname, utf *message) Creates an exception object with the given name and initalizes it with the given java/lang/String message. + IN: + classname....class name in UTF-8 + message......the message as a java.lang.String + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_exception_javastring(const char *classname, @@ -435,6 +480,14 @@ java_objectheader *new_exception_javastring(const char *classname, Creates an exception object with the given name and initalizes it with the given int value. + IN: + classname....class name in UTF-8 + i............the integer + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_exception_int(const char *classname, s4 i) @@ -454,10 +507,77 @@ java_objectheader *new_exception_int(const char *classname, s4 i) } +/* exceptions_new_abstractmethoderror ****************************************** + + Generates a java.lang.AbstractMethodError for the VM. + +*******************************************************************************/ + +java_objectheader *exceptions_new_abstractmethoderror(void) +{ + java_objectheader *e; + + e = native_new_and_init(class_java_lang_AbstractMethodError); + + if (e == NULL) + return *exceptionptr; + + return e; +} + + +/* exceptions_asm_new_abstractmethoderror ************************************** + + Generates a java.lang.AbstractMethodError for + asm_abstractmethoderror. + +*******************************************************************************/ + +java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra) +{ + stackframeinfo sfi; + java_objectheader *e; + + /* create the stackframeinfo (XPC is equal to RA) */ + + stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra); + + /* create the exception */ + + e = exceptions_new_abstractmethoderror(); + + /* remove the stackframeinfo */ + + stacktrace_remove_stackframeinfo(&sfi); + + return e; +} + + +/* exceptions_throw_abstractmethoderror **************************************** + + Generates a java.lang.AbstractMethodError for the VM and throws it. + +*******************************************************************************/ + +void exceptions_throw_abstractmethoderror(void) +{ + *exceptionptr = exceptions_new_abstractmethoderror(); +} + + /* new_classformaterror ******************************************************** generates a java.lang.ClassFormatError for the classloader + IN: + c............the class in which the error was found + message......UTF-8 format string + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...) @@ -472,7 +592,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...) msglen = 0; if (c) - msglen += utf_strlen(c->name) + strlen(" ("); + msglen += utf_bytes(c->name) + strlen(" ("); va_start(ap, message); msglen += get_variable_message_length(message, ap); @@ -490,7 +610,7 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...) /* print message into allocated buffer */ if (c) { - utf_sprint_classname(msg, c->name); + utf_copy_classname(msg, c->name); strcat(msg, " ("); } @@ -509,18 +629,53 @@ java_objectheader *new_classformaterror(classinfo *c, const char *message, ...) } +/* exceptions_throw_classformaterror ******************************************* + + Generate a java.lang.ClassFormatError for the VM system and throw it. + + IN: + c............the class in which the error was found + message......UTF-8 format string + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + +*******************************************************************************/ + +void exceptions_throw_classformaterror(classinfo *c, const char *message, ...) +{ + va_list ap; + + va_start(ap, message); + *exceptionptr = new_classformaterror(c, message, ap); + va_end(ap); +} + + /* new_classnotfoundexception ************************************************** Generates a java.lang.ClassNotFoundException for the classloader. + IN: + name.........name of the class not found as a utf * + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_classnotfoundexception(utf *name) { java_objectheader *o; + java_lang_String *s; + + s = javastring_new(name); + if (!s) + return *exceptionptr; - o = native_new_and_init_string(class_java_lang_ClassNotFoundException, - javastring_new(name)); + o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s); if (!o) return *exceptionptr; @@ -533,14 +688,25 @@ java_objectheader *new_classnotfoundexception(utf *name) Generates a java.lang.NoClassDefFoundError + IN: + name.........name of the class not found as a utf * + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_noclassdeffounderror(utf *name) { java_objectheader *o; + java_lang_String *s; + + s = javastring_new(name); + if (!s) + return *exceptionptr; - o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, - javastring_new(name)); + o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s); if (!o) return *exceptionptr; @@ -594,6 +760,13 @@ void classnotfoundexception_to_noclassdeffounderror(void) Generates a java.lang.InternalError for the VM. + IN: + message......UTF-8 message format string + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *new_internalerror(const char *message, ...) @@ -634,7 +807,15 @@ java_objectheader *new_internalerror(const char *message, ...) /* exceptions_new_linkageerror ************************************************* Generates a java.lang.LinkageError with an error message. - If c != NULL, the name of c is appended to the error message. + + IN: + message......UTF-8 message + c............class related to the error. If this is != NULL + the name of c is appended to the error message. + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). *******************************************************************************/ @@ -649,7 +830,7 @@ java_objectheader *exceptions_new_linkageerror(const char *message, msglen = strlen(message) + 1; if (c) { - msglen += utf_strlen(c->name); + msglen += utf_bytes(c->name); } /* allocate memory */ @@ -660,16 +841,19 @@ java_objectheader *exceptions_new_linkageerror(const char *message, strcpy(msg,message); if (c) { - utf_strcat(msg, c->name); + utf_cat_classname(msg, c->name); } o = native_new_and_init_string(class_java_lang_LinkageError, - javastring_new_char(msg)); + javastring_new_from_utf_string(msg)); /* free memory */ MFREE(msg, char, msglen); + if (!o) + return *exceptionptr; + return o; } @@ -678,6 +862,15 @@ java_objectheader *exceptions_new_linkageerror(const char *message, Generates a java.lang.NoSuchMethodError with an error message. + IN: + c............class in which the method was not found + name.........name of the method + desc.........descriptor of the method + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + *******************************************************************************/ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c, @@ -689,8 +882,8 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c, /* calculate exception message length */ - msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) + - utf_strlen(desc) + strlen("0"); + msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + + utf_bytes(desc) + strlen("0"); /* allocate memory */ @@ -698,25 +891,53 @@ java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c, /* generate message */ - utf_sprint(msg, c->name); + utf_copy_classname(msg, c->name); strcat(msg, "."); - utf_strcat(msg, name); - utf_strcat(msg, desc); + utf_cat(msg, name); + utf_cat(msg, desc); o = native_new_and_init_string(class_java_lang_NoSuchMethodError, - javastring_new_char(msg)); + javastring_new_from_utf_string(msg)); /* free memory */ MFREE(msg, char, msglen); + if (!o) + return *exceptionptr; + return o; } +/* exceptions_throw_nosuchmethoderror ****************************************** + + Generates a java.lang.NoSuchMethodError with an error message. + + IN: + c............class in which the method was not found + name.........name of the method + desc.........descriptor of the method + +*******************************************************************************/ + +void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc) +{ + *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc); +} + + /* new_unsupportedclassversionerror ******************************************** - generates a java.lang.UnsupportedClassVersionError for the classloader + Generate a java.lang.UnsupportedClassVersionError for the classloader + + IN: + c............class in which the method was not found + message......UTF-8 format string + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). *******************************************************************************/ @@ -729,7 +950,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me /* calculate exception message length */ - msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0"); + msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0"); va_start(ap, message); msglen += get_variable_message_length(message, ap); @@ -741,7 +962,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me /* generate message */ - utf_sprint_classname(msg, c->name); + utf_copy_classname(msg, c->name); strcat(msg, " ("); va_start(ap, message); @@ -763,13 +984,22 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me } -/* new_verifyerror ************************************************************* +/* exceptions_new_verifyerror ************************************************** - generates a java.lang.VerifyError for the jit compiler + Generates a java.lang.VerifyError for the JIT compiler. + + IN: + m............method in which the error was found + message......UTF-8 format string + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). *******************************************************************************/ -java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) +java_objectheader *exceptions_new_verifyerror(methodinfo *m, + const char *message, ...) { java_objectheader *o; va_list ap; @@ -783,9 +1013,9 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) msglen = 0; if (m) - msglen = strlen("(class: ") + utf_strlen(m->class->name) + - strlen(", method: ") + utf_strlen(m->name) + - strlen(" signature: ") + utf_strlen(m->descriptor) + + msglen = strlen("(class: ") + utf_bytes(m->class->name) + + strlen(", method: ") + utf_bytes(m->name) + + strlen(" signature: ") + utf_bytes(m->descriptor) + strlen(") ") + strlen("0"); va_start(ap, message); @@ -800,11 +1030,11 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) if (m) { strcpy(msg, "(class: "); - utf_strcat(msg, m->class->name); + utf_cat_classname(msg, m->class->name); strcat(msg, ", method: "); - utf_strcat(msg, m->name); + utf_cat(msg, m->name); strcat(msg, " signature: "); - utf_strcat(msg, m->descriptor); + utf_cat(msg, m->descriptor); strcat(msg, ") "); } @@ -824,6 +1054,94 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) } +/* exceptions_throw_verifyerror ************************************************ + + Throws a java.lang.VerifyError for the VM system. + +*******************************************************************************/ + +void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...) +{ + *exceptionptr = exceptions_new_verifyerror(m, message); +} + + +/* exceptions_throw_verifyerror_for_stack ************************************** + + throws a java.lang.VerifyError for an invalid stack slot type + + IN: + m............method in which the error was found + type.........the expected type + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + +*******************************************************************************/ + +void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type) +{ + java_objectheader *o; + char *msg; + s4 msglen; + char *typename; + + /* calculate exception message length */ + + msglen = 0; + + if (m) + msglen = strlen("(class: ") + utf_bytes(m->class->name) + + strlen(", method: ") + utf_bytes(m->name) + + strlen(" signature: ") + utf_bytes(m->descriptor) + + strlen(") Expecting to find longest-------typename on stack") + + strlen("0"); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + if (m) { + strcpy(msg, "(class: "); + utf_cat_classname(msg, m->class->name); + strcat(msg, ", method: "); + utf_cat(msg, m->name); + strcat(msg, " signature: "); + utf_cat(msg, m->descriptor); + strcat(msg, ") "); + } + else { + msg[0] = 0; + } + + strcat(msg,"Expecting to find "); + switch (type) { + case TYPE_INT: typename = "integer"; break; + case TYPE_LNG: typename = "long"; break; + case TYPE_FLT: typename = "float"; break; + case TYPE_DBL: typename = "double"; break; + case TYPE_ADR: typename = "object/array"; break; + case TYPE_RET: typename = "returnAddress"; break; + default: typename = ""; assert(0); break; + } + strcat(msg, typename); + strcat(msg, " on stack"); + + /* create exception object */ + + o = new_exception_message(string_java_lang_VerifyError, msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + *exceptionptr = o; +} + + /* new_arithmeticexception ***************************************************** Generates a java.lang.ArithmeticException for the jit compiler. @@ -844,18 +1162,19 @@ java_objectheader *new_arithmeticexception(void) } -/* new_arrayindexoutofboundsexception ****************************************** +/* exceptions_new_arrayindexoutofboundsexception ******************************* - Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT - compiler. + Generates a java.lang.ArrayIndexOutOfBoundsException for the VM + system. *******************************************************************************/ java_objectheader *new_arrayindexoutofboundsexception(s4 index) { java_objectheader *e; - methodinfo *m; - java_lang_String *s; + methodinfo *m; + java_objectheader *o; + java_lang_String *s; /* convert the index into a String, like Sun does */ @@ -865,35 +1184,53 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index) class_java_lang_Object, true); - if (!m) + if (m == NULL) return *exceptionptr; - s = (java_lang_String *) asm_calljavafunction(m, - (void *) (ptrint) index, - NULL, - NULL, - NULL); + o = vm_call_method(m, NULL, index); - if (!s) + s = (java_lang_String *) o; + + if (s == NULL) return *exceptionptr; e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException, s); - if (!e) + if (e == NULL) return *exceptionptr; return e; } -/* new_arraystoreexception ***************************************************** +/* exceptions_throw_arrayindexoutofboundsexception ***************************** + + Generates a java.lang.ArrayIndexOutOfBoundsException for the VM + system. + +*******************************************************************************/ + +void exceptions_throw_arrayindexoutofboundsexception(void) +{ + java_objectheader *e; + + e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + + if (!e) + return; + + *exceptionptr = e; +} + + +/* exceptions_new_arraystoreexception ****************************************** - generates a java.lang.ArrayStoreException for the jit compiler + Generates a java.lang.ArrayStoreException for the VM compiler. *******************************************************************************/ -java_objectheader *new_arraystoreexception(void) +java_objectheader *exceptions_new_arraystoreexception(void) { java_objectheader *e; @@ -907,26 +1244,45 @@ java_objectheader *new_arraystoreexception(void) } -/* new_classcastexception ****************************************************** +/* exceptions_throw_arraystoreexception **************************************** + + Generates a java.lang.ArrayStoreException for the VM system and + throw it in the VM system. + +*******************************************************************************/ + +void exceptions_throw_arraystoreexception(void) +{ + *exceptionptr = exceptions_new_arraystoreexception(); +} + + +/* exceptions_new_classcastexception ******************************************* - generates a java.lang.ClassCastException for the jit compiler + Generates a java.lang.ClassCastException for the JIT compiler. *******************************************************************************/ -java_objectheader *new_classcastexception(void) +java_objectheader *exceptions_new_classcastexception(java_objectheader *o) { java_objectheader *e; + utf *classname; + java_lang_String *s; - e = new_exception(string_java_lang_ClassCastException); + classname = o->vftbl->class->name; - if (!e) + s = javastring_new(classname); + + e = native_new_and_init_string(class_java_lang_ClassCastException, s); + + if (e == NULL) return *exceptionptr; return e; } -/* new_illegalargumentexception ************************************************ +/* exceptions_new_illegalargumentexception ************************************* Generates a java.lang.IllegalArgumentException for the VM system. @@ -936,34 +1292,64 @@ java_objectheader *new_illegalargumentexception(void) { java_objectheader *e; - if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException))) + e = native_new_and_init(class_java_lang_IllegalArgumentException); + + if (!e) return *exceptionptr; return e; } -/* new_illegalmonitorstateexception ******************************************** +/* exceptions_throw_illegalargumentexception *********************************** + + Generates a java.lang.IllegalArgumentException for the VM system + and throw it in the VM system. + +*******************************************************************************/ + +void exceptions_throw_illegalargumentexception(void) +{ + *exceptionptr = new_illegalargumentexception(); +} + + +/* exceptions_new_illegalmonitorstateexception ********************************* Generates a java.lang.IllegalMonitorStateException for the VM thread system. *******************************************************************************/ -java_objectheader *new_illegalmonitorstateexception(void) +java_objectheader *exceptions_new_illegalmonitorstateexception(void) { java_objectheader *e; - if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException))) + e = native_new_and_init(class_java_lang_IllegalMonitorStateException); + + if (e == NULL) return *exceptionptr; return e; } -/* new_negativearraysizeexception ********************************************** +/* exceptions_throw_illegalmonitorstateexception ******************************* + + Generates a java.lang.IllegalMonitorStateException for the VM + system and throw it in the VM system. + +*******************************************************************************/ + +void exceptions_throw_illegalmonitorstateexception(void) +{ + *exceptionptr = exceptions_new_illegalmonitorstateexception(); +} + + +/* exceptions_new_negativearraysizeexception *********************************** - generates a java.lang.NegativeArraySizeException for the jit compiler + Generates a java.lang.NegativeArraySizeException for the VM system. *******************************************************************************/ @@ -980,61 +1366,164 @@ java_objectheader *new_negativearraysizeexception(void) } -/* new_nullpointerexception **************************************************** +/* exceptions_throw_negativearraysizeexception ********************************* + + Generates a java.lang.NegativeArraySizeException for the VM system. + +*******************************************************************************/ + +void exceptions_throw_negativearraysizeexception(void) +{ + *exceptionptr = new_negativearraysizeexception(); +} + + +/* exceptions_new_nullpointerexception ***************************************** - generates a java.lang.NullPointerException for the jit compiler + Generates a java.lang.NullPointerException for the VM system. *******************************************************************************/ -java_objectheader *new_nullpointerexception(void) +java_objectheader *exceptions_new_nullpointerexception(void) { java_objectheader *e; e = native_new_and_init(class_java_lang_NullPointerException); - if (!e) + if (e == NULL) + return *exceptionptr; + + return e; +} + + +/* exceptions_throw_nullpointerexception *************************************** + + Generates a java.lang.NullPointerException for the VM system and + throw it in the VM system. + +*******************************************************************************/ + +void exceptions_throw_nullpointerexception(void) +{ + *exceptionptr = exceptions_new_nullpointerexception(); +} + + +/* exceptions_new_stringindexoutofboundsexception ****************************** + + Generates a java.lang.StringIndexOutOfBoundsException for the VM + system. + +*******************************************************************************/ + +java_objectheader *exceptions_new_stringindexoutofboundsexception(void) +{ + java_objectheader *e; + + e = new_exception(string_java_lang_StringIndexOutOfBoundsException); + + if (e == NULL) return *exceptionptr; return e; } +/* exceptions_throw_stringindexoutofboundsexception **************************** + + Throws a java.lang.StringIndexOutOfBoundsException for the VM + system. + +*******************************************************************************/ + +void exceptions_throw_stringindexoutofboundsexception(void) +{ + *exceptionptr = exceptions_new_stringindexoutofboundsexception(); +} + + +/* exceptions_get_and_clear_exception ****************************************** + + Gets the exception pointer of the current thread and clears it. + This function may return NULL. + +*******************************************************************************/ + +java_objectheader *exceptions_get_and_clear_exception(void) +{ + java_objectheader **p; + java_objectheader *e; + + /* get the pointer of the exception pointer */ + + p = exceptionptr; + + /* get the exception */ + + e = *p; + + /* and clear the exception */ + + *p = NULL; + + /* return the exception */ + + return e; +} + + /* exceptions_handle_exception ************************************************* - XXX + Try to find an exception handler for the given exception and return it. + If no handler is found, exit the monitor of the method (if any) + and return NULL. + + IN: + xptr.........the exception object + xpc..........PC of where the exception was thrown + pv...........Procedure Value of the current method + sp...........current stack pointer + + RETURN VALUE: + the address of the first matching exception handler, or + NULL if no handler was found *******************************************************************************/ +#if defined(ENABLE_JIT) u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp) { methodinfo *m; - s4 framesize; + codeinfo *code; s4 issync; - exceptionentry *ex; + dseg_exception_entry *ex; s4 exceptiontablelength; s4 i; classref_or_classinfo cr; classinfo *c; +#if defined(ENABLE_THREADS) java_objectheader *o; +#endif + + /* get info from the method header */ - /* get methodinfo pointer from method header */ + code = *((codeinfo **) (pv + CodeinfoPointer)); + issync = *((s4 *) (pv + IsSync)); + ex = (dseg_exception_entry *) (pv + ExTableStart); + exceptiontablelength = *((s4 *) (pv + ExTableSize)); - m = *((methodinfo **) (pv + MethodPointer)); - framesize = *((s4 *) (pv + FrameSize)); - issync = *((s4 *) (pv + IsSync)); - ex = (exceptionentry *) (pv + ExTableStart); - exceptiontablelength = *((s4 *) (pv + ExTableSize)); + /* Get the methodinfo pointer from the codeinfo pointer. For + asm_vm_call_method the codeinfo pointer is NULL. */ -/* if (m != NULL) { */ -/* printf("exceptions_handle_exception: "); */ -/* utf_display(m->class->name); */ -/* printf("."); */ -/* utf_display(m->name); */ -/* utf_display(m->descriptor); */ -/* printf(", %d\n", exceptiontablelength); */ -/* } */ + m = (code == NULL) ? NULL : code->m; - builtin_trace_exception(xptr, m, xpc, 1); +#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 @@ -1042,30 +1531,70 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp ex--; + /* If the start and end PC is NULL, this means we have the + special case of asm_vm_call_method. So, just return the + proper exception handler. */ + + if ((ex->startpc == NULL) && (ex->endpc == NULL)) + return (u1 *) (ptrint) &asm_vm_call_method_exception_handler; + /* is the xpc is the current catch range */ - if (ex->startpc <= xpc && xpc < ex->endpc) { + if ((ex->startpc <= xpc) && (xpc < ex->endpc)) { cr = ex->catchtype; /* NULL catches everything */ - if (cr.any == NULL) + if (cr.any == NULL) { +#if !defined(NDEBUG) + /* Print stacktrace of exception when caught. */ + + if (opt_verboseexception) { + exceptions_print_exception(xptr); + stacktrace_print_trace(xptr); + } +#endif + return ex->handlerpc; + } /* resolve or load/link the exception class */ if (IS_CLASSREF(cr)) { + /* The exception class reference is unresolved. */ + /* We have to do _eager_ resolving here. While the class of */ + /* the exception object is guaranteed to be loaded, it may */ + /* well have been loaded by a different loader than the */ + /* defining loader of m's class, which is the one we must */ + /* use to resolve the catch class. Thus lazy resolving */ + /* might fail, even if the result of the resolution would */ + /* be an already loaded class. */ + c = resolve_classref_eager(cr.ref); + if (c == NULL) { + /* Exception resolving the exception class, argh! */ + return NULL; + } + + /* Ok, we resolved it. Enter it in the table, so we don't */ + /* have to do this again. */ + /* XXX this write should be atomic. Is it? */ + + ex->catchtype.cls = c; } else { c = cr.cls; + /* XXX I don't think this case can ever happen. -Edwin */ if (!(c->state & CLASS_LOADED)) /* use the methods' classloader */ if (!load_class_from_classloader(c->name, m->class->classloader)) return NULL; + /* XXX I think, if it is not linked, we can be sure that */ + /* the exception object is no (indirect) instance of it, no? */ + /* -Edwin */ if (!(c->state & CLASS_LINKED)) if (!link_class(c)) return NULL; @@ -1073,22 +1602,37 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp /* is the thrown exception an instance of the catch class? */ - if (builtin_instanceof(xptr, c)) + if (builtin_instanceof(xptr, c)) { +#if !defined(NDEBUG) + /* Print stacktrace of exception when caught. */ + + if (opt_verboseexception) { + exceptions_print_exception(xptr); + stacktrace_print_trace(xptr); + } +#endif + return ex->handlerpc; + } } } -#if defined(USE_THREADS) +#if defined(ENABLE_THREADS) /* is this method synchronized? */ if (issync) { /* 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); + assert(o != NULL); - builtin_monitorexit(o); + lock_monitor_exit(o); } #endif @@ -1096,6 +1640,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp return NULL; } +#endif /* defined(ENABLE_JIT) */ /* exceptions_print_exception ************************************************** @@ -1112,32 +1657,38 @@ void exceptions_print_exception(java_objectheader *xptr) utf *u; t = (java_lang_Throwable *) xptr; + + if (t == NULL) { + puts("NULL\n"); + return; + } + cause = t->cause; /* print the root exception */ - utf_display_classname(t->header.vftbl->class->name); + utf_display_printable_ascii_classname(t->header.vftbl->class->name); if (t->detailMessage) { u = javastring_toutf(t->detailMessage, false); printf(": "); - utf_display(u); + utf_display_printable_ascii(u); } putc('\n', stdout); /* print the cause if available */ - if (cause && (cause != t)) { + if ((cause != NULL) && (cause != t)) { printf("Caused by: "); - utf_display_classname(cause->header.vftbl->class->name); + utf_display_printable_ascii_classname(cause->header.vftbl->class->name); if (cause->detailMessage) { u = javastring_toutf(cause->detailMessage, false); printf(": "); - utf_display(u); + utf_display_printable_ascii(u); } putc('\n', stdout); @@ -1156,4 +1707,5 @@ void exceptions_print_exception(java_objectheader *xptr) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */