X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fexceptions.c;h=6a340702f6d46ebf34ac87cd05c95b3faad9f2ee;hb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;hp=b15d34f4591f2ed864f2c142bfdda1006937c3e3;hpb=89d1d5fccbffaf391b5df32aca43292297d3fcaa;p=cacao.git diff --git a/src/vm/exceptions.c b/src/vm/exceptions.c index b15d34f45..6a340702f 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,16 +19,8 @@ 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. - - Contact: cacao@complang.tuwien.ac.at - - Authors: Christian Thalinger - - Changes: Edwin Steiner - - $Id: exceptions.c 3931 2005-12-09 15:09:13Z twisti $ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ @@ -39,30 +31,53 @@ #include #include #include +#include +#include #include "vm/types.h" +#include "md-abi.h" + #include "mm/memory.h" + +#include "native/jni.h" +#include "native/llni.h" #include "native/native.h" + #include "native/include/java_lang_String.h" #include "native/include/java_lang_Throwable.h" -#include "toolbox/logging.h" + +#include "threads/lock-common.h" +#include "threads/threads-common.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/vm.h" + #include "vm/jit/asmpart.h" #include "vm/jit/jit.h" #include "vm/jit/methodheader.h" +#include "vm/jit/patcher-common.h" +#include "vm/jit/stacktrace.h" + +#include "vmcore/class.h" +#include "vmcore/loader.h" +#include "vmcore/method.h" +#include "vmcore/options.h" + +#if defined(ENABLE_VMLOG) +#include +#endif /* for raising exceptions from native methods *********************************/ -#if !defined(USE_THREADS) || !defined(NATIVE_THREADS) -java_objectheader *_no_threads_exceptionptr = NULL; +#if !defined(ENABLE_THREADS) +java_object_t *_no_threads_exceptionptr = NULL; #endif @@ -74,6 +89,25 @@ java_objectheader *_no_threads_exceptionptr = NULL; bool exceptions_init(void) { +#if !(defined(__ARM__) && defined(__LINUX__)) + /* On arm-linux the first memory page can't be mmap'ed, as it + contains the exception vectors. */ + + int pagesize; + + /* mmap a memory page at address 0x0, so our hardware-exceptions + work. */ + + pagesize = getpagesize(); + + (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED); +#endif + + /* check if we get into trouble with our hardware-exceptions */ + + if (OFFSET(java_bytearray_t, data) <= EXCEPTION_HARDWARE_LARGEST) + vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray_t, data), EXCEPTION_HARDWARE_LARGEST); + /* java/lang/Throwable */ if (!(class_java_lang_Throwable = @@ -81,40 +115,26 @@ 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; - /* java/lang/NoClassDefFoundError */ - - if (!(class_java_lang_NoClassDefFoundError = - load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) || - !link_class(class_java_lang_NoClassDefFoundError)) - 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/NoSuchMethodError */ + /* java/lang/NoClassDefFoundError */ - if (!(class_java_lang_NoSuchMethodError = - load_class_bootstrap(utf_java_lang_NoSuchMethodError)) || - !link_class(class_java_lang_NoSuchMethodError)) + if (!(class_java_lang_NoClassDefFoundError = + load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) || + !link_class(class_java_lang_NoClassDefFoundError)) return false; /* java/lang/OutOfMemoryError */ @@ -124,6 +144,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 */ @@ -132,6 +159,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 = @@ -139,20 +173,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 = @@ -161,631 +181,1086 @@ bool exceptions_init(void) return false; - return true; -} - - -static void throw_exception_exit_intern(bool doexit) -{ - java_objectheader *xptr; - classinfo *c; - methodinfo *pss; - - xptr = *exceptionptr; +#if defined(WITH_CLASSPATH_GNU) + /* java/lang/VMThrowable */ - if (xptr) { - /* clear exception, because we are calling jit code again */ - *exceptionptr = NULL; + if (!(class_java_lang_VMThrowable = + load_class_bootstrap(utf_java_lang_VMThrowable)) || + !link_class(class_java_lang_VMThrowable)) + return false; +#endif - c = xptr->vftbl->class; + return true; +} - pss = class_resolveclassmethod(c, - utf_printStackTrace, - utf_void__void, - class_java_lang_Object, - false); - /* print the stacktrace */ - if (pss) { - asm_calljavafunction(pss, xptr, NULL, NULL, NULL); +/* exceptions_get_exception **************************************************** - /* This normally means, we are EXTREMLY out of memory or have a */ - /* serious problem while printStackTrace. But may be another */ - /* exception, so print it. */ + Returns the current exception pointer of the current thread. - if (*exceptionptr) { - java_lang_Throwable *t; +*******************************************************************************/ - t = (java_lang_Throwable *) *exceptionptr; +java_handle_t *exceptions_get_exception(void) +{ + /* return the exception */ - fprintf(stderr, "Exception while printStackTrace(): "); - utf_fprint_classname(stderr, t->header.vftbl->class->name); + return *exceptionptr; +} - if (t->detailMessage) { - char *buf; - buf = javastring_tochar((java_objectheader *) t->detailMessage); - fprintf(stderr, ": %s", buf); - MFREE(buf, char, strlen(buf)); - } - - fprintf(stderr, "\n"); - } +/* exceptions_set_exception **************************************************** - } else { - utf_fprint_classname(stderr, c->name); - fprintf(stderr, ": printStackTrace()V not found!\n"); - } + Sets the exception pointer of the current thread. - fflush(stderr); +*******************************************************************************/ - /* good bye! */ +void exceptions_set_exception(java_handle_t *o) +{ + /* set the exception */ - if (doexit) - exit(1); - } + *exceptionptr = o; } -void throw_exception(void) -{ - throw_exception_exit_intern(false); -} +/* exceptions_clear_exception ************************************************** + Clears the current exception pointer of the current thread. -void throw_exception_exit(void) -{ - throw_exception_exit_intern(true); -} - +*******************************************************************************/ -void throw_main_exception(void) +void exceptions_clear_exception(void) { - fprintf(stderr, "Exception in thread \"main\" "); - fflush(stderr); - - throw_exception_exit_intern(false); + exceptions_set_exception(NULL); } -void throw_main_exception_exit(void) -{ - fprintf(stderr, "Exception in thread \"main\" "); - fflush(stderr); +/* exceptions_get_and_clear_exception ****************************************** - throw_exception_exit_intern(true); -} + Gets the exception pointer of the current thread and clears it. + This function may return NULL. +*******************************************************************************/ -void throw_cacao_exception_exit(const char *exception, const char *message, ...) +java_handle_t *exceptions_get_and_clear_exception(void) { - s4 i; - char *tmp; - s4 len; - va_list ap; + java_handle_t *o; - len = strlen(exception); - tmp = MNEW(char, len + 1); - strncpy(tmp, exception, len); - tmp[len] = '\0'; + /* get the exception */ - /* convert to classname */ + o = exceptions_get_exception(); - for (i = len - 1; i >= 0; i--) - if (tmp[i] == '/') tmp[i] = '.'; + /* and clear the exception */ - fprintf(stderr, "Exception in thread \"main\" %s", tmp); + exceptions_clear_exception(); - MFREE(tmp, char, len); + /* return the exception */ - if (strlen(message) > 0) { - fprintf(stderr, ": "); + return o; +} - va_start(ap, message); - vfprintf(stderr, message, ap); - va_end(ap); - } - fprintf(stderr, "\n"); - fflush(stderr); +/* exceptions_new_class ******************************************************** - /* good bye! */ + Creates an exception object from the given class and initalizes it. - exit(1); -} + IN: + class....class pointer +*******************************************************************************/ -/* exceptions_throw_outofmemory_exit ******************************************* +static java_handle_t *exceptions_new_class(classinfo *c) +{ + java_handle_t *o; - Just print an: java.lang.InternalError: Out of memory + o = native_new_and_init(c); -*******************************************************************************/ + if (o == NULL) + return exceptions_get_exception(); -void exceptions_throw_outofmemory_exit(void) -{ - throw_cacao_exception_exit(string_java_lang_InternalError, - "Out of memory"); + return o; } -/* new_exception *************************************************************** +/* exceptions_new_utf ********************************************************** Creates an exception object with the given name and initalizes it. + IN: + classname....class name in UTF-8 + *******************************************************************************/ -java_objectheader *new_exception(const char *classname) +static java_handle_t *exceptions_new_utf(utf *classname) { - java_objectheader *o; - classinfo *c; + classinfo *c; + java_handle_t *o; - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + c = load_class_bootstrap(classname); - o = native_new_and_init(c); + if (c == NULL) + return exceptions_get_exception(); - if (!o) - return *exceptionptr; + o = exceptions_new_class(c); return o; } -/* new_exception_message ******************************************************* +/* exceptions_throw_class ****************************************************** - Creates an exception object with the given name and initalizes it - with the given char message. + Creates an exception object from the given class, initalizes and + throws it. + + IN: + class....class pointer *******************************************************************************/ -java_objectheader *new_exception_message(const char *classname, - const char *message) +static void exceptions_throw_class(classinfo *c) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + java_handle_t *o; - o = native_new_and_init_string(c, javastring_new_char(message)); + o = exceptions_new_class(c); - if (!o) - return *exceptionptr; + if (o == NULL) + return; - return o; + exceptions_set_exception(o); } -/* new_exception_throwable ***************************************************** +/* exceptions_throw_utf ******************************************************** - Creates an exception object with the given name and initalizes it - with the given java/lang/Throwable exception. + Creates an exception object with the given name, initalizes and + throws it. + + IN: + classname....class name in UTF-8 *******************************************************************************/ -java_objectheader *new_exception_throwable(const char *classname, - java_lang_Throwable *throwable) +static void exceptions_throw_utf(utf *classname) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + classinfo *c; - o = native_new_and_init_throwable(c, throwable); + c = load_class_bootstrap(classname); - if (!o) - return *exceptionptr; + if (c == NULL) + return; - return o; + exceptions_throw_class(c); } -/* new_exception_utfmessage **************************************************** +/* exceptions_throw_utf_throwable ********************************************** Creates an exception object with the given name and initalizes it - with the given utf message. + with the given java/lang/Throwable exception. + + IN: + classname....class name in UTF-8 + cause........the given Throwable *******************************************************************************/ -java_objectheader *new_exception_utfmessage(const char *classname, utf *message) +static void exceptions_throw_utf_throwable(utf *classname, + java_handle_t *cause) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + classinfo *c; + java_handle_t *o; + methodinfo *m; + java_lang_Throwable *object; - o = native_new_and_init_string(c, javastring_new(message)); + object = (java_lang_Throwable *) cause; - if (!o) - return *exceptionptr; + c = load_class_bootstrap(classname); - return o; + if (c == NULL) + return; + + /* create object */ + + o = builtin_new(c); + + if (o == NULL) + return; + + /* call initializer */ + + m = class_resolveclassmethod(c, + utf_init, + utf_java_lang_Throwable__void, + NULL, + true); + + if (m == NULL) + return; + + (void) vm_call_method(m, o, cause); + + exceptions_set_exception(o); } -/* new_exception_javastring **************************************************** +/* exceptions_throw_utf_exception ********************************************** Creates an exception object with the given name and initalizes it - with the given java/lang/String message. + with the given java/lang/Exception exception. + + IN: + classname....class name in UTF-8 + exception....the given Exception *******************************************************************************/ -java_objectheader *new_exception_javastring(const char *classname, - java_lang_String *message) +static void exceptions_throw_utf_exception(utf *classname, + java_handle_t *exception) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + classinfo *c; + java_handle_t *o; + methodinfo *m; - o = native_new_and_init_string(c, message); + c = load_class_bootstrap(classname); - if (!o) - return *exceptionptr; + if (c == NULL) + return; - return o; + /* create object */ + + o = builtin_new(c); + + if (o == NULL) + return; + + /* call initializer */ + + m = class_resolveclassmethod(c, + utf_init, + utf_java_lang_Exception__V, + NULL, + true); + + if (m == NULL) + return; + + (void) vm_call_method(m, o, exception); + + exceptions_set_exception(o); } -/* new_exception_int *********************************************************** +/* exceptions_throw_utf_cause ************************************************** Creates an exception object with the given name and initalizes it - with the given int value. + with the given java/lang/Throwable exception with initCause. + + IN: + classname....class name in UTF-8 + cause........the given Throwable *******************************************************************************/ -java_objectheader *new_exception_int(const char *classname, s4 i) +static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause) { - java_objectheader *o; - classinfo *c; - - if (!(c = load_class_bootstrap(utf_new_char(classname)))) - return *exceptionptr; + classinfo *c; + java_handle_t *o; + methodinfo *m; + java_lang_String *s; + java_lang_Throwable *object; - o = native_new_and_init_int(c, i); + object = (java_lang_Throwable *) cause; - if (!o) - return *exceptionptr; + c = load_class_bootstrap(classname); - return o; -} + if (c == NULL) + return; + /* create object */ -/* new_classformaterror ******************************************************** + o = builtin_new(c); + + if (o == NULL) + return; - generates a java.lang.ClassFormatError for the classloader + /* call initializer */ -*******************************************************************************/ + m = class_resolveclassmethod(c, + utf_init, + utf_java_lang_String__void, + NULL, + true); + + if (m == NULL) + return; -java_objectheader *new_classformaterror(classinfo *c, const char *message, ...) -{ - java_objectheader *o; - char *msg; - s4 msglen; - va_list ap; + LLNI_field_get_ref(object, detailMessage, s); - /* calculate message length */ + (void) vm_call_method(m, o, s); - msglen = 0; + /* call initCause */ - if (c) - msglen += utf_strlen(c->name) + strlen(" ("); + m = class_resolveclassmethod(c, + utf_initCause, + utf_java_lang_Throwable__java_lang_Throwable, + NULL, + true); - va_start(ap, message); - msglen += get_variable_message_length(message, ap); - va_end(ap); + if (m == NULL) + return; - if (c) - msglen += strlen(")"); + (void) vm_call_method(m, o, cause); - msglen += strlen("0"); + exceptions_set_exception(o); +} - /* allocate a buffer */ - msg = MNEW(char, msglen); +/* exceptions_new_utf_javastring *********************************************** - /* print message into allocated buffer */ + Creates an exception object with the given name and initalizes it + with the given java/lang/String message. - if (c) { - utf_sprint_classname(msg, c->name); - strcat(msg, " ("); - } + IN: + classname....class name in UTF-8 + message......the message as a java.lang.String - va_start(ap, message); - vsprintf(msg + strlen(msg), message, ap); - va_end(ap); + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). - if (c) - strcat(msg, ")"); +*******************************************************************************/ - o = new_exception_message(string_java_lang_ClassFormatError, msg); +static java_handle_t *exceptions_new_utf_javastring(utf *classname, + java_handle_t *message) +{ + java_handle_t *o; + classinfo *c; + + c = load_class_bootstrap(classname); - MFREE(msg, char, msglen); + if (c == NULL) + return exceptions_get_exception(); + + o = native_new_and_init_string(c, message); + + if (o == NULL) + return exceptions_get_exception(); return o; } -/* new_classnotfoundexception ************************************************** +/* exceptions_new_class_utf **************************************************** - Generates a java.lang.ClassNotFoundException for the classloader. + 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_classnotfoundexception(utf *name) +static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message) { - java_objectheader *o; + java_handle_t *o; + java_handle_t *s; + + s = javastring_new(message); - o = native_new_and_init_string(class_java_lang_ClassNotFoundException, - javastring_new(name)); + if (s == NULL) + return exceptions_get_exception(); - if (!o) - return *exceptionptr; + o = native_new_and_init_string(c, s); + + if (o == NULL) + return exceptions_get_exception(); return o; } -/* new_noclassdeffounderror **************************************************** +/* exceptions_new_utf_utf ****************************************************** + + 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 * - Generates a java.lang.NoClassDefFoundError + 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) +static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message) { - java_objectheader *o; + classinfo *c; + java_handle_t *o; + + c = load_class_bootstrap(classname); - o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, - javastring_new(name)); + if (c == NULL) + return exceptions_get_exception(); - if (!o) - return *exceptionptr; + o = exceptions_new_class_utf(c, message); return o; } -/* classnotfoundexception_to_noclassdeffounderror ****************************** +/* exceptions_throw_class_utf ************************************************** - Check the *exceptionptr for a ClassNotFoundException. If it is one, - convert it to a NoClassDefFoundError. + 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 *******************************************************************************/ -void classnotfoundexception_to_noclassdeffounderror(void) +static void exceptions_throw_class_utf(classinfo *c, utf *message) { - java_objectheader *xptr; - java_objectheader *cause; + java_handle_t *o; - /* get the cause */ - - cause = *exceptionptr; + o = exceptions_new_class_utf(c, message); - /* convert ClassNotFoundException's to NoClassDefFoundError's */ + exceptions_set_exception(o); +} - if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) { - /* clear exception, because we are calling jit code again */ - *exceptionptr = NULL; +/* exceptions_throw_utf_utf **************************************************** - /* create new error */ + Creates an exception object with the given name, initalizes and + throws it with the given utf message. - xptr = - new_exception_javastring(string_java_lang_NoClassDefFoundError, - ((java_lang_Throwable *) cause)->detailMessage); + IN: + classname....class name in UTF-8 + message......the message as an utf * - /* we had an exception while creating the error */ +*******************************************************************************/ - if (*exceptionptr) - return; +static void exceptions_throw_utf_utf(utf *classname, utf *message) +{ + java_handle_t *o; - /* set new exception */ + o = exceptions_new_utf_utf(classname, message); - *exceptionptr = xptr; - } + exceptions_set_exception(o); } -/* new_internalerror *********************************************************** +/* exceptions_new_abstractmethoderror **************************************** - Generates a java.lang.InternalError for the VM. + Generates a java.lang.AbstractMethodError for the VM. *******************************************************************************/ -java_objectheader *new_internalerror(const char *message, ...) +java_handle_t *exceptions_new_abstractmethoderror(void) { - java_objectheader *o; - va_list ap; - char *msg; - s4 msglen; - - /* calculate exception message length */ - - va_start(ap, message); - msglen = get_variable_message_length(message, ap); - va_end(ap); + java_handle_t *o; - /* allocate memory */ + o = exceptions_new_utf(utf_java_lang_AbstractMethodError); - msg = MNEW(char, msglen); + return o; +} - /* generate message */ - va_start(ap, message); - vsprintf(msg, message, ap); - va_end(ap); +/* exceptions_new_error ******************************************************** - /* create exception object */ + Generates a java.lang.Error for the VM. - o = new_exception_message(string_java_lang_InternalError, msg); +*******************************************************************************/ - /* free memory */ +#if defined(ENABLE_JAVAME_CLDC1_1) +static java_handle_t *exceptions_new_error(utf *message) +{ + java_handle_t *o; - MFREE(msg, char, msglen); + o = exceptions_new_class_utf(class_java_lang_Error, message); return o; } +#endif -/* exceptions_new_linkageerror ************************************************* +/* exceptions_asm_new_abstractmethoderror ************************************** - Generates a java.lang.LinkageError with an error message. - If c != NULL, the name of c is appended to the error message. + Generates a java.lang.AbstractMethodError for + asm_abstractmethoderror. *******************************************************************************/ -java_objectheader *exceptions_new_linkageerror(const char *message, - classinfo *c) +java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra) { - java_objectheader *o; - char *msg; - s4 msglen; + stackframeinfo sfi; + java_handle_t *e; - /* calculate exception message length */ - - msglen = strlen(message) + 1; - if (c) { - msglen += utf_strlen(c->name); - } - - /* allocate memory */ - - msg = MNEW(char, msglen); + /* create the stackframeinfo (XPC is equal to RA) */ - /* generate message */ + stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra); - strcpy(msg,message); - if (c) { - utf_strcat(msg, c->name); - } + /* create the exception */ - o = native_new_and_init_string(class_java_lang_LinkageError, - javastring_new_char(msg)); +#if defined(ENABLE_JAVASE) + e = exceptions_new_abstractmethoderror(); +#else + e = exceptions_new_error(utf_java_lang_AbstractMethodError); +#endif - /* free memory */ + /* remove the stackframeinfo */ - MFREE(msg, char, msglen); + stacktrace_remove_stackframeinfo(&sfi); - return o; + return e; } -/* exceptions_new_nosuchmethoderror ******************************************** +/* exceptions_new_arraystoreexception ****************************************** - Generates a java.lang.NoSuchMethodError with an error message. + Generates a java.lang.ArrayStoreException for the VM. *******************************************************************************/ -java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c, - utf *name, utf *desc) +java_handle_t *exceptions_new_arraystoreexception(void) { - java_objectheader *o; - char *msg; - s4 msglen; + java_handle_t *o; - /* calculate exception message length */ + o = exceptions_new_utf(utf_java_lang_ArrayStoreException); - msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) + - utf_strlen(desc) + strlen("0"); + return o; +} - /* allocate memory */ - msg = MNEW(char, msglen); +/* exceptions_throw_abstractmethoderror **************************************** - /* generate message */ + Generates and throws a java.lang.AbstractMethodError for the VM. - utf_sprint(msg, c->name); - strcat(msg, "."); - utf_strcat(msg, name); - utf_strcat(msg, desc); +*******************************************************************************/ - o = native_new_and_init_string(class_java_lang_NoSuchMethodError, - javastring_new_char(msg)); +void exceptions_throw_abstractmethoderror(void) +{ + exceptions_throw_utf(utf_java_lang_AbstractMethodError); +} - /* free memory */ - MFREE(msg, char, msglen); +/* exceptions_throw_classcircularityerror ************************************** - return o; + Generates and throws a java.lang.ClassCircularityError for the + classloader. + + IN: + c....the class in which the error was found + +*******************************************************************************/ + +void exceptions_throw_classcircularityerror(classinfo *c) +{ + exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name); } -/* new_unsupportedclassversionerror ******************************************** +/* exceptions_throw_classformaterror ******************************************* + + Generates and throws a java.lang.ClassFormatError for the VM. - generates a java.lang.UnsupportedClassVersionError for the classloader + IN: + c............the class in which the error was found + message......UTF-8 format string *******************************************************************************/ -java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...) +void exceptions_throw_classformaterror(classinfo *c, const char *message, ...) { - java_objectheader *o; - va_list ap; - char *msg; - s4 msglen; + char *msg; + s4 msglen; + va_list ap; + utf *u; - /* calculate exception message length */ + /* calculate message length */ + + msglen = 0; - msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0"); + if (c != NULL) + msglen += utf_bytes(c->name) + strlen(" ("); va_start(ap, message); 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 */ - utf_sprint_classname(msg, c->name); - strcat(msg, " ("); + if (c != NULL) { + utf_copy_classname(msg, c->name); + strcat(msg, " ("); + } va_start(ap, message); vsprintf(msg + strlen(msg), message, ap); va_end(ap); + if (c != NULL) + strcat(msg, ")"); + + u = utf_new_char(msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + /* throw exception */ + + exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u); +} + + +/* 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_cause ********************************* + + Generates and throws a java.lang.NoClassDefFoundError with the + given cause. + +*******************************************************************************/ + +void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause) +{ + exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause); +} + + +/* 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, ")"); - /* create exception object */ + u = utf_new_char(msg); + + MFREE(msg, char, msglen); + + exceptions_throw_noclassdeffounderror(u); +} + - o = new_exception_message(string_java_lang_UnsupportedClassVersionError, - msg); +/* exceptions_throw_exceptionininitializererror ******************************** + + Generates and throws a java.lang.ExceptionInInitializerError for + the VM. + + IN: + cause......cause exception object + +*******************************************************************************/ + +void exceptions_throw_exceptionininitializererror(java_handle_t *cause) +{ + exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError, + cause); +} + + +/* exceptions_throw_incompatibleclasschangeerror ******************************* + + Generates and throws a java.lang.IncompatibleClassChangeError for + the VM. + + IN: + message......UTF-8 message format string + +*******************************************************************************/ + +void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message) +{ + char *msg; + s4 msglen; + utf *u; + + /* calculate exception message length */ + + msglen = utf_bytes(c->name) + strlen(message) + strlen("0"); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + utf_copy_classname(msg, c->name); + strcat(msg, message); + + u = utf_new_char(msg); /* free memory */ MFREE(msg, char, msglen); - return o; + /* throw exception */ + + exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u); +} + + +/* 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); +} + + +/* exceptions_throw_internalerror ********************************************** + + Generates and throws a java.lang.InternalError for the VM. + + IN: + message......UTF-8 message format string + +*******************************************************************************/ + +void exceptions_throw_internalerror(const char *message, ...) +{ + va_list ap; + char *msg; + s4 msglen; + utf *u; + + /* calculate exception message length */ + + va_start(ap, message); + msglen = get_variable_message_length(message, ap); + va_end(ap); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + va_start(ap, message); + vsprintf(msg, message, ap); + va_end(ap); + + u = utf_new_char(msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + /* throw exception */ + + exceptions_throw_utf_utf(utf_java_lang_InternalError, u); +} + + +/* exceptions_throw_linkageerror *********************************************** + + Generates and throws java.lang.LinkageError with an 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. + +*******************************************************************************/ + +void exceptions_throw_linkageerror(const char *message, classinfo *c) +{ + java_handle_t *o; + char *msg; + s4 msglen; + + /* calculate exception message length */ + + msglen = strlen(message) + 1; + + if (c != NULL) + msglen += utf_bytes(c->name); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + strcpy(msg,message); + + if (c != NULL) + utf_cat_classname(msg, c->name); + + o = native_new_and_init_string(class_java_lang_LinkageError, + javastring_new_from_utf_string(msg)); + + /* free memory */ + + MFREE(msg, char, msglen); + + if (o == NULL) + return; + + exceptions_set_exception(o); +} + + +/* exceptions_throw_nosuchfielderror ******************************************* + + Generates and throws a java.lang.NoSuchFieldError with an error + message. + + IN: + c............class in which the field was not found + name.........name of the field + +*******************************************************************************/ + +void exceptions_throw_nosuchfielderror(classinfo *c, utf *name) +{ + char *msg; + s4 msglen; + utf *u; + + /* calculate exception message length */ + + msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0"); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + utf_copy_classname(msg, c->name); + strcat(msg, "."); + utf_cat(msg, name); + + u = utf_new_char(msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u); } -/* new_verifyerror ************************************************************* +/* exceptions_throw_nosuchmethoderror ****************************************** - generates a java.lang.VerifyError for the jit compiler + Generates and throws 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 *******************************************************************************/ -java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) +void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc) { - java_objectheader *o; - va_list ap; - char *msg; - s4 msglen; + char *msg; + s4 msglen; + utf *u; + + /* calculate exception message length */ + + msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + + utf_bytes(desc) + strlen("0"); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + utf_copy_classname(msg, c->name); + strcat(msg, "."); + utf_cat(msg, name); + utf_cat(msg, desc); + + u = utf_new_char(msg); + + /* free memory */ + + MFREE(msg, char, msglen); + +#if defined(ENABLE_JAVASE) + exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u); +#else + exceptions_throw_class_utf(class_java_lang_Error, u); +#endif +} + + +/* exceptions_throw_outofmemoryerror ******************************************* + + Generates and throws an java.lang.OutOfMemoryError for the VM. + +*******************************************************************************/ + +void exceptions_throw_outofmemoryerror(void) +{ + exceptions_throw_class(class_java_lang_OutOfMemoryError); +} + + +/* exceptions_throw_unsatisfiedlinkerror *************************************** + + Generates and throws a java.lang.UnsatisfiedLinkError for the + classloader. + + IN: + name......UTF-8 name string + +*******************************************************************************/ + +void exceptions_throw_unsatisfiedlinkerror(utf *name) +{ +#if defined(ENABLE_JAVASE) + exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name); +#else + exceptions_throw_class_utf(class_java_lang_Error, name); +#endif +} + + +/* exceptions_throw_unsupportedclassversionerror ******************************* + + 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 + +*******************************************************************************/ + +void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi) +{ + char *msg; + s4 msglen; + utf *u; + + /* calculate exception message length */ + + msglen = + utf_bytes(c->name) + + strlen(" (Unsupported major.minor version 00.0)") + + strlen("0"); + + /* allocate memory */ + + msg = MNEW(char, msglen); + + /* generate message */ + + utf_copy_classname(msg, c->name); + sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)", + ma, mi); + + u = utf_new_char(msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + /* throw exception */ + + exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u); +} + + +/* exceptions_throw_verifyerror ************************************************ + + Generates and throws a java.lang.VerifyError for the JIT compiler. - useinlining = false; /* at least until sure inlining works with exceptions*/ + IN: + m............method in which the error was found + message......UTF-8 format string + +*******************************************************************************/ + +void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...) +{ + va_list ap; + char *msg; + s4 msglen; + utf *u; /* 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) + + 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); @@ -798,13 +1273,13 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) /* generate message */ - if (m) { + if (m != NULL) { 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, ") "); } @@ -812,50 +1287,125 @@ java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...) vsprintf(msg + strlen(msg), message, ap); va_end(ap); - /* create exception object */ - - o = new_exception_message(string_java_lang_VerifyError, msg); + u = utf_new_char(msg); /* free memory */ MFREE(msg, char, msglen); - return o; + /* throw exception */ + + exceptions_throw_utf_utf(utf_java_lang_VerifyError, u); } -/* new_arithmeticexception ***************************************************** +/* exceptions_throw_verifyerror_for_stack ************************************** + + throws a java.lang.VerifyError for an invalid stack slot type - Generates a java.lang.ArithmeticException for the jit compiler. + 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). *******************************************************************************/ -java_objectheader *new_arithmeticexception(void) +void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type) { - java_objectheader *e; + char *msg; + s4 msglen; + char *typename; + utf *u; - e = new_exception_message(string_java_lang_ArithmeticException, - string_java_lang_ArithmeticException_message); + /* 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(") Expecting to find longest-------typename on stack") + + strlen("0"); + + /* 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, ") "); + } + 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"); + + u = utf_new_char(msg); + + /* free memory */ + + MFREE(msg, char, msglen); + + /* throw exception */ + + exceptions_throw_utf_utf(utf_java_lang_VerifyError, u); +} + + +/* exceptions_new_arithmeticexception ****************************************** + + Generates a java.lang.ArithmeticException for the JIT compiler. + +*******************************************************************************/ + +java_handle_t *exceptions_new_arithmeticexception(void) +{ + java_handle_t *o; + + o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException, + utf_division_by_zero); + + return o; } -/* 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_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index) { - java_objectheader *e; - methodinfo *m; - java_lang_String *s; + java_handle_t *o; + methodinfo *m; + java_handle_t *s; /* convert the index into a String, like Sun does */ @@ -865,181 +1415,380 @@ java_objectheader *new_arrayindexoutofboundsexception(s4 index) class_java_lang_Object, true); - if (!m) - return *exceptionptr; + if (m == NULL) + return exceptions_get_exception(); - s = (java_lang_String *) asm_calljavafunction(m, - (void *) (ptrint) index, - NULL, - NULL, - NULL); + s = vm_call_method(m, NULL, index); - if (!s) - return *exceptionptr; + if (s == NULL) + return exceptions_get_exception(); - e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException, - s); + o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException, + s); - if (!e) - return *exceptionptr; + if (o == NULL) + return exceptions_get_exception(); - return e; + return o; } -/* new_arraystoreexception ***************************************************** +/* exceptions_throw_arrayindexoutofboundsexception ***************************** - generates a java.lang.ArrayStoreException for the jit compiler + Generates and throws a java.lang.ArrayIndexOutOfBoundsException for + the VM. *******************************************************************************/ -java_objectheader *new_arraystoreexception(void) +void exceptions_throw_arrayindexoutofboundsexception(void) { - java_objectheader *e; + exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException); +} + + +/* exceptions_throw_arraystoreexception **************************************** - e = new_exception(string_java_lang_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_handle_t *exceptions_new_classcastexception(java_handle_t *o) +{ + java_handle_t *e; + utf *classname; - if (!e) - return *exceptionptr; + classname = o->vftbl->class->name; + + e = exceptions_new_class_utf(class_java_lang_ClassCastException, classname); return e; } -/* new_classcastexception ****************************************************** +/* exceptions_throw_clonenotsupportedexception ********************************* - generates a java.lang.ClassCastException for the jit compiler + Generates and throws a java.lang.CloneNotSupportedException for the + VM. *******************************************************************************/ -java_objectheader *new_classcastexception(void) +void exceptions_throw_clonenotsupportedexception(void) { - java_objectheader *e; + exceptions_throw_utf(utf_java_lang_CloneNotSupportedException); +} - e = new_exception(string_java_lang_ClassCastException); - if (!e) - return *exceptionptr; +/* exceptions_throw_illegalaccessexception ************************************* - return e; + Generates and throws a java.lang.IllegalAccessException for the VM. + +*******************************************************************************/ + +void exceptions_throw_illegalaccessexception(utf *message) +{ + exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message); } -/* new_illegalargumentexception ************************************************ +/* exceptions_throw_illegalargumentexception *********************************** - Generates a java.lang.IllegalArgumentException for the VM system. + Generates and throws a java.lang.IllegalArgumentException for the + VM. *******************************************************************************/ -java_objectheader *new_illegalargumentexception(void) +void exceptions_throw_illegalargumentexception(void) { - java_objectheader *e; + exceptions_throw_utf(utf_java_lang_IllegalArgumentException); +} - if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException))) - return *exceptionptr; - return e; +/* 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); } -/* new_illegalmonitorstateexception ******************************************** +/* exceptions_throw_instantiationexception ************************************* - Generates a java.lang.IllegalMonitorStateException for the VM - thread system. + Generates and throws a java.lang.InstantiationException for the VM. *******************************************************************************/ -java_objectheader *new_illegalmonitorstateexception(void) +void exceptions_throw_instantiationexception(classinfo *c) { - java_objectheader *e; + exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name); +} - if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException))) - return *exceptionptr; - return e; +/* 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); } -/* new_negativearraysizeexception ********************************************** +/* exceptions_throw_invocationtargetexception ********************************** + + Generates and throws a java.lang.reflect.InvocationTargetException + for the VM. - generates a java.lang.NegativeArraySizeException for the jit compiler + IN: + cause......cause exception object *******************************************************************************/ -java_objectheader *new_negativearraysizeexception(void) +void exceptions_throw_invocationtargetexception(java_handle_t *cause) { - java_objectheader *e; + exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException, + cause); +} - e = new_exception(string_java_lang_NegativeArraySizeException); - if (!e) - return *exceptionptr; +/* exceptions_throw_negativearraysizeexception ********************************* - return e; + Generates and throws a java.lang.NegativeArraySizeException for the + VM. + +*******************************************************************************/ + +void exceptions_throw_negativearraysizeexception(void) +{ + exceptions_throw_utf(utf_java_lang_NegativeArraySizeException); } -/* new_nullpointerexception **************************************************** +/* 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_handle_t *exceptions_new_nullpointerexception(void) { - java_objectheader *e; + java_handle_t *o; - e = native_new_and_init(class_java_lang_NullPointerException); + o = exceptions_new_class(class_java_lang_NullPointerException); - if (!e) - return *exceptionptr; + return o; +} - 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) +{ + exceptions_throw_class(class_java_lang_NullPointerException); +} + + +/* exceptions_throw_privilegedactionexception ********************************** + + Generates and throws a java.security.PrivilegedActionException. + +*******************************************************************************/ + +void exceptions_throw_privilegedactionexception(java_handle_t *exception) +{ + exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException, + exception); +} + + +/* 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_classnotfoundexception_to_noclassdeffounderror ******************* + + Check the exception for a ClassNotFoundException. If it is one, + convert it to a NoClassDefFoundError. + +*******************************************************************************/ + +void exceptions_classnotfoundexception_to_noclassdeffounderror(void) +{ + java_handle_t *o; + java_handle_t *cause; + java_lang_Throwable *object; + java_lang_String *s; + + /* get the cause */ + + cause = exceptions_get_exception(); + + /* convert ClassNotFoundException's to NoClassDefFoundError's */ + + if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) { + /* clear exception, because we are calling jit code again */ + + exceptions_clear_exception(); + + /* create new error */ + + object = (java_lang_Throwable *) cause; + LLNI_field_get_ref(object, detailMessage, s); + + o = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError, + (java_handle_t *) s); + + /* we had an exception while creating the error */ + + if (exceptions_get_exception()) + return; + + /* set new exception */ + + exceptions_set_exception(o); + } +} + + +/* exceptions_fillinstacktrace ************************************************* + + Calls the fillInStackTrace-method of the currently thrown + exception. + +*******************************************************************************/ + +java_handle_t *exceptions_fillinstacktrace(void) +{ + java_handle_t *o; + methodinfo *m; + + /* get exception */ + + o = exceptions_get_and_clear_exception(); + + assert(o); + + /* resolve methodinfo pointer from exception object */ + +#if defined(ENABLE_JAVASE) + m = class_resolvemethod(o->vftbl->class, + utf_fillInStackTrace, + utf_void__java_lang_Throwable); +#elif defined(ENABLE_JAVAME_CLDC1_1) + m = class_resolvemethod(o->vftbl->class, + utf_fillInStackTrace, + utf_void__void); +#else +#error IMPLEMENT ME! +#endif + + /* call function */ + + (void) vm_call_method(m, o); + + /* return exception object */ + + return o; } /* 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 *******************************************************************************/ -u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp) +#if defined(ENABLE_JIT) +u1 *exceptions_handle_exception(java_object_t *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; - java_objectheader *o; - - /* get methodinfo pointer from method header */ - - m = *((methodinfo **) (pv + MethodPointer)); - framesize = *((s4 *) (pv + FrameSize)); - issync = *((s4 *) (pv + IsSync)); - ex = (exceptionentry *) (pv + ExTableStart); - exceptiontablelength = *((s4 *) (pv + ExTableSize)); - -#if 0 - if (m != NULL) { - printf("exceptions_handle_exception(%p, %p, %p, %p): ", xptr, xpc, pv, sp); - utf_display(m->class->name); - printf("."); - utf_display(m->name); - utf_display(m->descriptor); - printf(", %d\n", exceptiontablelength); - } +#if defined(ENABLE_THREADS) + java_object_t *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 || runverbose || opt_verboseexception) + if (opt_verbose || opt_verbosecall || opt_TraceExceptions) builtin_trace_exception(xptr, m, xpc, 1); +#endif + +#if defined(ENABLE_VMLOG) + vmlog_cacao_throw(xptr); +#endif for (i = 0; i < exceptiontablelength; i++) { /* ATTENTION: keep this here, as we need to decrement the @@ -1047,30 +1796,74 @@ 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 ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(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 defined(ENABLE_VMLOG) + vmlog_cacao_catch(xptr); +#endif + + if (opt_TraceExceptions) { + 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; @@ -1078,34 +1871,53 @@ 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 defined(ENABLE_VMLOG) + vmlog_cacao_catch(xptr); +#endif + + if (opt_TraceExceptions) { + 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) +# if (defined(__MIPS__) && (SIZEOF_VOID_P == 4)) || defined(__I386__) || defined(__S390__) || defined(__POWERPC__) /* XXX change this if we ever want to use 4-byte stackslots */ - o = *((java_objectheader **) (sp + issync - 8)); + o = *((java_object_t **) (sp + issync - 8)); # else - o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P)); -#endif + o = *((java_object_t **) (sp + issync - SIZEOF_VOID_P)); +# endif assert(o != NULL); - builtin_monitorexit(o); + lock_monitor_exit(o); } #endif /* none of the exceptions catch this one */ +#if defined(ENABLE_VMLOG) + vmlog_cacao_unwnd_method(m); +#endif + return NULL; } +#endif /* defined(ENABLE_JIT) */ /* exceptions_print_exception ************************************************** @@ -1115,43 +1927,153 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp *******************************************************************************/ -void exceptions_print_exception(java_objectheader *xptr) +void exceptions_print_exception(java_handle_t *xptr) { java_lang_Throwable *t; +#if defined(ENABLE_JAVASE) java_lang_Throwable *cause; +#endif + java_lang_String *s; + classinfo *c; utf *u; t = (java_lang_Throwable *) xptr; - cause = t->cause; + + if (t == NULL) { + puts("NULL\n"); + return; + } + +#if defined(ENABLE_JAVASE) + LLNI_field_get_ref(t, cause, cause); +#endif /* print the root exception */ - utf_display_classname(t->header.vftbl->class->name); + LLNI_class_get(t, c); + utf_display_printable_ascii_classname(c->name); - if (t->detailMessage) { - u = javastring_toutf(t->detailMessage, false); + LLNI_field_get_ref(t, detailMessage, s); + + if (s != NULL) { + u = javastring_toutf((java_handle_t *) s, false); printf(": "); - utf_display(u); + utf_display_printable_ascii(u); } putc('\n', stdout); +#if defined(ENABLE_JAVASE) /* 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); + + LLNI_class_get(cause, c); + utf_display_printable_ascii_classname(c->name); - if (cause->detailMessage) { - u = javastring_toutf(cause->detailMessage, false); + LLNI_field_get_ref(cause, detailMessage, s); + + if (s != NULL) { + u = javastring_toutf((java_handle_t *) s, false); printf(": "); - utf_display(u); + 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_handle_t *o; + + o = exceptions_get_exception(); + + exceptions_print_exception(o); +} + + +/* 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_handle_t *oxptr; + java_handle_t *xptr; + classinfo *c; + methodinfo *m; + + /* get original exception */ + + oxptr = exceptions_get_and_clear_exception(); + + if (oxptr == NULL) + vm_abort("exceptions_print_stacktrace: no exception thrown"); + + /* clear exception, because we are calling jit code again */ + + 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 = exceptions_get_exception(); + + 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); } @@ -1166,4 +2088,5 @@ void exceptions_print_exception(java_objectheader *xptr) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */