X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fexceptions.c;h=2b3f71ba8eb52a82de096d86b3e03c9290824369;hb=d1e7b2f4023800d98aab37d22abc9b449e9822eb;hp=fc0c5efe18bca0e5a0f128e17ed0721bcc7fe149;hpb=be47443ba144bee4cc538896ee3f7b51e6a4fe70;p=cacao.git diff --git a/src/vm/exceptions.c b/src/vm/exceptions.c index fc0c5efe1..2b3f71ba8 100644 --- a/src/vm/exceptions.c +++ b/src/vm/exceptions.c @@ -1,9 +1,7 @@ /* src/vm/exceptions.c - exception related functions - 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 + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -31,7 +29,6 @@ #include #include #include -#include #include #include "vm/types.h" @@ -45,10 +42,11 @@ #include "native/native.h" #include "native/include/java_lang_String.h" +#include "native/include/java_lang_Thread.h" #include "native/include/java_lang_Throwable.h" #include "threads/lock-common.h" -#include "threads/threads-common.h" +#include "threads/thread.h" #include "toolbox/util.h" @@ -70,6 +68,7 @@ #include "vmcore/loader.h" #include "vmcore/method.h" #include "vmcore/options.h" +#include "vmcore/system.h" #if defined(ENABLE_VMLOG) #include @@ -100,11 +99,13 @@ void exceptions_init(void) /* mmap a memory page at address 0x0, so our hardware-exceptions work. */ - pagesize = getpagesize(); + pagesize = system_getpagesize(); - (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED); + (void) system_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED); #endif + TRACESUBSYSTEMINITIALIZATION("exceptions_init"); + /* check if we get into trouble with our hardware-exceptions */ if (OFFSET(java_bytearray_t, data) <= EXCEPTION_HARDWARE_LARGEST) @@ -276,6 +277,44 @@ static void exceptions_abort(utf *classname, utf *message) } +/* exceptions_new_class_utf **************************************************** + + Creates an exception object with the given class and initalizes it + with the given utf message. + + IN: + c ......... exception class + 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). + +*******************************************************************************/ + +static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message) +{ + java_handle_t *s; + java_handle_t *o; + + if (vm_initializing) + exceptions_abort(c->name, message); + + s = javastring_new(message); + + if (s == NULL) + return exceptions_get_exception(); + + o = native_new_and_init_string(c, s); + + if (o == NULL) + return exceptions_get_exception(); + + return o; +} + + /* exceptions_new_utf ********************************************************** Creates an exception object with the given name and initalizes it. @@ -307,6 +346,99 @@ static java_handle_t *exceptions_new_utf(utf *classname) } +/* exceptions_new_utf_javastring *********************************************** + + 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). + +*******************************************************************************/ + +static java_handle_t *exceptions_new_utf_javastring(utf *classname, + java_handle_t *message) +{ + java_handle_t *o; + classinfo *c; + + if (vm_initializing) + exceptions_abort(classname, NULL); + + c = load_class_bootstrap(classname); + + if (c == NULL) + return exceptions_get_exception(); + + o = native_new_and_init_string(c, message); + + if (o == NULL) + return exceptions_get_exception(); + + return o; +} + + +/* 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 * + + RETURN VALUE: + an exception pointer (in any case -- either it is the newly created + exception, or an exception thrown while trying to create it). + +*******************************************************************************/ + +static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message) +{ + classinfo *c; + java_handle_t *o; + + if (vm_initializing) + exceptions_abort(classname, message); + + c = load_class_bootstrap(classname); + + if (c == NULL) + return exceptions_get_exception(); + + o = exceptions_new_class_utf(c, message); + + return o; +} + + +/* exceptions_throw_class_utf ************************************************** + + Creates an exception object with the given class, initalizes and + throws it with the given utf message. + + IN: + c ......... exception class + message ... the message as an utf * + +*******************************************************************************/ + +static void exceptions_throw_class_utf(classinfo *c, utf *message) +{ + java_handle_t *o; + + o = exceptions_new_class_utf(c, message); + + exceptions_set_exception(o); +} + + /* exceptions_throw_utf ******************************************************** Creates an exception object with the given name, initalizes and @@ -501,87 +633,6 @@ static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause) } -/* exceptions_new_utf_javastring *********************************************** - - 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). - -*******************************************************************************/ - -static java_handle_t *exceptions_new_utf_javastring(utf *classname, - java_handle_t *message) -{ - java_handle_t *o; - classinfo *c; - - if (vm_initializing) - exceptions_abort(classname, NULL); - - c = load_class_bootstrap(classname); - - if (c == NULL) - return exceptions_get_exception(); - - o = native_new_and_init_string(c, message); - - if (o == NULL) - return exceptions_get_exception(); - - return o; -} - - -/* 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 * - - RETURN VALUE: - an exception pointer (in any case -- either it is the newly created - exception, or an exception thrown while trying to create it). - -*******************************************************************************/ - -static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message) -{ - classinfo *c; - java_handle_t *s; - java_handle_t *o; - - if (vm_initializing) - exceptions_abort(classname, message); - - c = load_class_bootstrap(classname); - - if (c == NULL) - return exceptions_get_exception(); - - s = javastring_new(message); - - if (s == NULL) - return exceptions_get_exception(); - - o = native_new_and_init_string(c, s); - - if (o == NULL) - return exceptions_get_exception(); - - return o; -} - - /* exceptions_throw_utf_utf **************************************************** Creates an exception object with the given name, initalizes and @@ -794,7 +845,7 @@ void exceptions_throw_classformaterror(classinfo *c, const char *message, ...) void exceptions_throw_classnotfoundexception(utf *name) { - exceptions_throw_utf_utf(utf_java_lang_ClassNotFoundException, name); + exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name); } @@ -1589,60 +1640,6 @@ void exceptions_throw_stringindexoutofboundsexception(void) } -/* 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) -{ - classinfo *c; - java_handle_t *o; - java_handle_t *cause; - java_lang_Throwable *object; - java_lang_String *s; - - /* Load java/lang/ClassNotFoundException for the instanceof - check. */ - - c = load_class_bootstrap(utf_java_lang_ClassNotFoundException); - - if (c == NULL) - return; - - /* Get the cause. */ - - cause = exceptions_get_exception(); - - /* Convert ClassNotFoundException's to NoClassDefFoundError's. */ - - if (builtin_instanceof(cause, c)) { - /* 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 @@ -1707,26 +1704,25 @@ java_handle_t *exceptions_fillinstacktrace(void) *******************************************************************************/ #if defined(ENABLE_JIT) -u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) +void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp) { - stackframeinfo_t sfi; - java_handle_t *xptr; - methodinfo *m; - codeinfo *code; - s4 issync; - dseg_exception_entry *ex; - s4 exceptiontablelength; - s4 i; - classref_or_classinfo cr; - classinfo *c; + stackframeinfo_t sfi; + java_handle_t *xptr; + methodinfo *m; + codeinfo *code; + exceptiontable_t *et; + exceptiontable_entry_t *ete; + s4 i; + classref_or_classinfo cr; + classinfo *c; #if defined(ENABLE_THREADS) - java_object_t *o; + java_object_t *o; #endif - u1 *result; + void *result; #ifdef __S390__ /* Addresses are 31 bit integers */ -# define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF) +# define ADDR_MASK(x) (void *) ((uintptr_t) (x) & 0x7FFFFFFF) #else # define ADDR_MASK(x) (x) #endif @@ -1740,17 +1736,20 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) result = NULL; - /* get info from the method header */ + /* Get the codeinfo for the current method. */ - code = *((codeinfo **) (pv + CodeinfoPointer)); - issync = *((s4 *) (pv + IsSync)); - ex = (dseg_exception_entry *) (pv + ExTableStart); - exceptiontablelength = *((s4 *) (pv + ExTableSize)); + code = code_get_codeinfo_for_pv(pv); /* Get the methodinfo pointer from the codeinfo pointer. For - asm_vm_call_method the codeinfo pointer is NULL. */ + asm_vm_call_method the codeinfo pointer is NULL and we simply + can return the proper exception handler. */ + + if (code == NULL) { + result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler; + goto exceptions_handle_exception_return; + } - m = (code == NULL) ? NULL : code->m; + m = code->m; #if !defined(NDEBUG) /* print exception trace */ @@ -1763,25 +1762,20 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) # endif #endif - for (i = 0; i < exceptiontablelength; i++) { - /* ATTENTION: keep this here, as we need to decrement the - pointer before the loop executes! */ + /* Get the exception table. */ - ex--; + et = code->exceptiontable; - /* 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 (et != NULL) { + /* Iterate over all exception table entries. */ - if ((ex->startpc == NULL) && (ex->endpc == NULL)) { - result = (u1 *) (ptrint) &asm_vm_call_method_exception_handler; - goto exceptions_handle_exception_return; - } + ete = et->entries; + for (i = 0; i < et->length; i++, ete++) { /* is the xpc is the current catch range */ - if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) { - cr = ex->catchtype; + if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) { + cr = ete->catchtype; /* NULL catches everything */ @@ -1795,11 +1789,11 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) if (opt_TraceExceptions) { exceptions_print_exception(xptr); - stacktrace_print_trace(xptr); + stacktrace_print_exception(xptr); } #endif - result = ex->handlerpc; + result = ete->handlerpc; goto exceptions_handle_exception_return; } @@ -1807,13 +1801,14 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) 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. */ + /* 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); @@ -1822,12 +1817,13 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) goto exceptions_handle_exception_return; } - /* 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? */ + /* 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 { + ete->catchtype.cls = c; + } + else { c = cr.cls; /* XXX I don't think this case can ever happen. -Edwin */ @@ -1837,9 +1833,9 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) m->class->classloader)) goto exceptions_handle_exception_return; - /* XXX I think, if it is not linked, we can be sure that */ - /* the exception object is no (indirect) instance of it, no? */ - /* -Edwin */ + /* 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)) goto exceptions_handle_exception_return; @@ -1857,32 +1853,28 @@ u1 *exceptions_handle_exception(java_object_t *xptro, u1 *xpc, u1 *pv, u1 *sp) if (opt_TraceExceptions) { exceptions_print_exception(xptr); - stacktrace_print_trace(xptr); + stacktrace_print_exception(xptr); } #endif - result = ex->handlerpc; + result = ete->handlerpc; goto exceptions_handle_exception_return; } } } + } #if defined(ENABLE_THREADS) - /* is this method synchronized? */ + /* Is this method realization synchronized? */ - if (issync) { - /* get synchronization object */ + if (code_is_synchronized(code)) { + /* Get synchronization object. */ -# 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_object_t **) (sp + issync - 8)); -# else - o = *((java_object_t **) (sp + issync - SIZEOF_VOID_P)); -# endif + o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset)); assert(o != NULL); - lock_monitor_exit(o); + lock_monitor_exit(LLNI_QUICKWRAP(o)); } #endif @@ -2021,63 +2013,100 @@ void exceptions_print_current_exception(void) void exceptions_print_stacktrace(void) { - java_handle_t *oxptr; - java_handle_t *xptr; - classinfo *c; - methodinfo *m; + java_handle_t *e; + java_handle_t *ne; + classinfo *c; + methodinfo *m; + +#if defined(ENABLE_THREADS) + threadobject *t; + java_lang_Thread *to; +#endif + + /* Get and clear exception because we are calling Java code + again. */ - /* get original exception */ + e = exceptions_get_and_clear_exception(); - oxptr = exceptions_get_and_clear_exception(); + if (e == NULL) + return; - if (oxptr == NULL) - vm_abort("exceptions_print_stacktrace: no exception thrown"); +#if 0 + /* FIXME Enable me. */ + if (builtin_instanceof(e, class_java_lang_ThreadDeath)) { + /* Don't print anything if we are being killed. */ + } + else +#endif + { + /* Get the exception class. */ - /* clear exception, because we are calling jit code again */ + LLNI_class_get(e, c); - LLNI_class_get(oxptr, c); + /* Find the printStackTrace() method. */ - /* find the printStackTrace() method */ + m = class_resolveclassmethod(c, + utf_printStackTrace, + utf_void__void, + class_java_lang_Object, + false); - 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"); - if (m == NULL) - vm_abort("exceptions_print_stacktrace: printStackTrace()V not found"); + /* Print message. */ + + fprintf(stderr, "Exception "); + +#if defined(ENABLE_THREADS) + /* Print thread name. We get the thread here explicitly as we + need it afterwards. */ - /* print compatibility message */ + t = thread_get_current(); + to = (java_lang_Thread *) thread_get_object(t); - fprintf(stderr, "Exception in thread \"main\" "); + if (to != NULL) { + fprintf(stderr, "in thread \""); + thread_fprint_name(t, stderr); + fprintf(stderr, "\" "); + } +#endif - /* print the stacktrace */ + /* Print the stacktrace. */ - (void) vm_call_method(m, oxptr); + if (builtin_instanceof(e, class_java_lang_Throwable)) { + (void) vm_call_method(m, e); - /* This normally means, we are EXTREMLY out of memory or - have a serious problem while printStackTrace. But may - be another exception, so print it. */ + /* If this happens 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(); + ne = exceptions_get_exception(); - if (xptr != NULL) { - fprintf(stderr, "Exception while printStackTrace(): "); + if (ne != NULL) { + fprintf(stderr, "Exception while printStackTrace(): "); - /* now print original exception */ + /* Print the current exception. */ - exceptions_print_exception(xptr); - stacktrace_print_trace(xptr); + exceptions_print_exception(ne); + stacktrace_print_exception(ne); - /* now print original exception */ + /* Now print the original exception. */ - fprintf(stderr, "Original exception was: "); - exceptions_print_exception(oxptr); - stacktrace_print_trace(oxptr); - } + fprintf(stderr, "Original exception was: "); + exceptions_print_exception(e); + stacktrace_print_exception(e); + } + } + else { + fprintf(stderr, ". Uncaught exception of type "); + /* FIXME This prints to stdout. */ + class_print(c); + fprintf(stderr, "."); + } - fflush(stderr); + fflush(stderr); + } }