* src/vm/jit/x86_64/codegen.c (codegen): Changed to use the macros VAR and VAROP.
[cacao.git] / src / vm / exceptions.c
index d2edfd2f4886c8cf2cd03648428df9db9af5d9bf..41d13867b97a67644e1bf7b9af1bc389debad132 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Edwin Steiner
 
-   $Id: exceptions.c 4879 2006-05-05 17:34:49Z edwin $
+   $Id: exceptions.c 5586 2006-09-29 14:21:42Z edwin $
 
 */
 
@@ -62,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
 
@@ -97,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 */
@@ -111,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 =
@@ -133,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 =
@@ -493,6 +507,65 @@ 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
@@ -911,7 +984,7 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 }
 
 
-/* new_verifyerror *************************************************************
+/* exceptions_new_verifyerror **************************************************
 
    Generates a java.lang.VerifyError for the JIT compiler.
 
@@ -925,7 +998,8 @@ java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *me
 
 *******************************************************************************/
 
-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;
@@ -980,6 +1054,18 @@ 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
@@ -1038,6 +1124,7 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
                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 = "<INVALID>"; assert(0); break;
        }
        strcat(msg, typename);
@@ -1054,6 +1141,7 @@ void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
        *exceptionptr = o;
 }
 
+
 /* new_arithmeticexception *****************************************************
 
    Generates a java.lang.ArithmeticException for the jit compiler.
@@ -1136,13 +1224,13 @@ void exceptions_throw_arrayindexoutofboundsexception(void)
 }
 
 
-/* new_arraystoreexception *****************************************************
+/* 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;
 
@@ -1156,19 +1244,38 @@ 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;
@@ -1207,26 +1314,39 @@ void exceptions_throw_illegalargumentexception(void)
 }
 
 
-/* new_illegalmonitorstateexception ********************************************
+/* 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;
 
        e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
 
-       if (!e)
+       if (e == NULL)
                return *exceptionptr;
 
        return e;
 }
 
 
+/* 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 VM system.
@@ -1323,6 +1443,36 @@ void exceptions_throw_stringindexoutofboundsexception(void)
 }
 
 
+/* 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 *************************************************
 
    Try to find an exception handler for the given exception and return it.
@@ -1344,6 +1494,7 @@ void exceptions_throw_stringindexoutofboundsexception(void)
 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
 {
        methodinfo            *m;
+       codeinfo              *code;
        s4                     framesize;
        s4                     issync;
        exceptionentry        *ex;
@@ -1351,18 +1502,23 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
        s4                     i;
        classref_or_classinfo  cr;
        classinfo             *c;
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
        java_objectheader     *o;
 #endif
 
-       /* get methodinfo pointer from method header */
+       /* get info from the method header */
 
-       m                    = *((methodinfo **)    (pv + MethodPointer));
+       code                 = *((codeinfo **)      (pv + CodeinfoPointer));
        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. */
+
+       m = (code == NULL) ? NULL : code->m;
+
 #if !defined(NDEBUG)
        /* print exception trace */
 
@@ -1406,17 +1562,40 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
                        /* 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;
@@ -1439,7 +1618,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
                }
        }
 
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
        /* is this method synchronized? */
 
        if (issync) {
@@ -1454,7 +1633,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp
 
                assert(o != NULL);
 
-               builtin_monitorexit(o);
+               lock_monitor_exit(o);
        }
 #endif