-/* exceptions.c - exception related functions
+/* src/vm/exceptions.c - exception related functions
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
- M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
- P. Tomsich, J. Wenninger
+ 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
This file is part of CACAO.
Authors: Christian Thalinger
- $Id: exceptions.c 1410 2004-08-17 13:01:24Z twisti $
+ Changes:
+
+ $Id: exceptions.c 2671 2005-06-13 14:29:42Z twisti $
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
-#include "asmpart.h"
-#include "global.h"
-#include "loader.h"
-#include "native.h"
-#include "tables.h"
-#include "jit/jit.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "nat/java_lang_String.h"
-#include "nat/java_lang_Throwable.h"
-
-
-/* system exception classes required in cacao */
-
-classinfo *class_java_lang_Throwable;
-classinfo *class_java_lang_Exception;
-classinfo *class_java_lang_Error;
-classinfo *class_java_lang_OutOfMemoryError;
-
-
-/* exception/error super class */
-
-char *string_java_lang_Throwable =
- "java/lang/Throwable";
-
-char *string_java_lang_VMThrowable =
- "java/lang/VMThrowable";
-
-
-/* specify some exception strings for code generation */
-
-char *string_java_lang_ArithmeticException =
- "java/lang/ArithmeticException";
-
-char *string_java_lang_ArithmeticException_message =
- "/ by zero";
-
-char *string_java_lang_ArrayIndexOutOfBoundsException =
- "java/lang/ArrayIndexOutOfBoundsException";
-
-char *string_java_lang_ArrayStoreException =
- "java/lang/ArrayStoreException";
-
-char *string_java_lang_ClassCastException =
- "java/lang/ClassCastException";
-
-char *string_java_lang_ClassNotFoundException =
- "java/lang/ClassNotFoundException";
-
-char *string_java_lang_CloneNotSupportedException =
- "java/lang/CloneNotSupportedException";
-
-char *string_java_lang_Exception =
- "java/lang/Exception";
-
-char *string_java_lang_IllegalArgumentException =
- "java/lang/IllegalArgumentException";
-
-char *string_java_lang_IllegalMonitorStateException =
- "java/lang/IllegalMonitorStateException";
-
-char *string_java_lang_IndexOutOfBoundsException =
- "java/lang/IndexOutOfBoundsException";
-
-char *string_java_lang_InterruptedException =
- "java/lang/InterruptedException";
-
-char *string_java_lang_NegativeArraySizeException =
- "java/lang/NegativeArraySizeException";
-
-char *string_java_lang_NoSuchFieldException =
- "java/lang/NoSuchFieldException";
-
-char *string_java_lang_NoSuchMethodException =
- "java/lang/NoSuchMethodException";
-char *string_java_lang_NullPointerException =
- "java/lang/NullPointerException";
+#include "config.h"
+#include "mm/memory.h"
+#include "native/native.h"
+#include "native/include/java_lang_String.h"
+#include "native/include/java_lang_Throwable.h"
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+#include "vm/class.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+
+
+/* for raising exceptions from native methods */
+
+#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
+java_objectheader* _exceptionptr = NULL;
+u1 _dontfillinexceptionstacktrace = false;
+#endif
-/* specify some error strings for code generation */
-
-char *string_java_lang_AbstractMethodError =
- "java/lang/AbstractMethodError";
-
-char *string_java_lang_ClassCircularityError =
- "java/lang/ClassCircularityError";
-
-char *string_java_lang_ClassFormatError =
- "java/lang/ClassFormatError";
-char *string_java_lang_Error =
- "java/lang/Error";
+/* init_system_exceptions ******************************************************
-char *string_java_lang_ExceptionInInitializerError =
- "java/lang/ExceptionInInitializerError";
+ Load and link exceptions used in the system.
-char *string_java_lang_IncompatibleClassChangeError =
- "java/lang/IncompatibleClassChangeError";
+*******************************************************************************/
-char *string_java_lang_InternalError =
- "java/lang/InternalError";
+bool exceptions_init(void)
+{
+ /* java/lang/Throwable */
-char *string_java_lang_LinkageError =
- "java/lang/LinkageError";
+ if (!(class_java_lang_Throwable =
+ load_class_bootstrap(utf_java_lang_Throwable)) ||
+ !link_class(class_java_lang_Throwable))
+ return false;
-char *string_java_lang_NoClassDefFoundError =
- "java/lang/NoClassDefFoundError";
-char *string_java_lang_NoSuchFieldError =
- "java/lang/NoSuchFieldError";
+ /* java/lang/VMThrowable */
-char *string_java_lang_NoSuchMethodError =
- "java/lang/NoSuchMethodError";
+ if (!(class_java_lang_VMThrowable =
+ load_class_bootstrap(utf_java_lang_VMThrowable)) ||
+ !link_class(class_java_lang_VMThrowable))
+ return false;
-char *string_java_lang_OutOfMemoryError =
- "java/lang/OutOfMemoryError";
-char *string_java_lang_UnsupportedClassVersionError =
- "java/lang/UnsupportedClassVersionError";
+ /* java/lang/Error */
-char *string_java_lang_VerifyError =
- "java/lang/VerifyError";
+ if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
+ !link_class(class_java_lang_Error))
+ return false;
-char *string_java_lang_VirtualMachineError =
- "java/lang/VirtualMachineError";
+ /* java/lang/Exception */
-/* init_system_exceptions *****************************************************
+ if (!(class_java_lang_Exception =
+ load_class_bootstrap(utf_java_lang_Exception)) ||
+ !link_class(class_java_lang_Exception))
+ return false;
- load, link and compile exceptions used in the system
-*******************************************************************************/
+ /* java/lang/NoClassDefFoundError */
-void init_system_exceptions()
-{
- /* java/lang/Throwable */
+ if (!(class_java_lang_NoClassDefFoundError =
+ load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
+ !link_class(class_java_lang_NoClassDefFoundError))
+ return false;
- class_java_lang_Throwable =
- class_new(utf_new_char(string_java_lang_Throwable));
- class_load(class_java_lang_Throwable);
- class_link(class_java_lang_Throwable);
- /* java/lang/Exception */
+ /* java/lang/OutOfMemoryError */
- class_java_lang_Exception =
- class_new(utf_new_char(string_java_lang_Exception));
- class_load(class_java_lang_Exception);
- class_link(class_java_lang_Exception);
+ if (!(class_java_lang_OutOfMemoryError =
+ load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
+ !link_class(class_java_lang_OutOfMemoryError))
+ return false;
- /* java/lang/Error */
- class_java_lang_Error =
- class_new(utf_new_char(string_java_lang_Error));
- class_load(class_java_lang_Error);
- class_link(class_java_lang_Error);
+ /* java/lang/ClassNotFoundException */
- /* java/lang/OutOfMemoryError */
+ if (!(class_java_lang_ClassNotFoundException =
+ load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
+ !link_class(class_java_lang_ClassNotFoundException))
+ return false;
- class_java_lang_OutOfMemoryError =
- class_new(utf_new_char(string_java_lang_OutOfMemoryError));
- class_load(class_java_lang_OutOfMemoryError);
- class_link(class_java_lang_OutOfMemoryError);
+ return true;
}
classinfo *c;
methodinfo *pss;
- if (*exceptionptr) {
- xptr = *exceptionptr;
+ xptr = *exceptionptr;
+ if (xptr) {
/* clear exception, because we are calling jit code again */
*exceptionptr = NULL;
c = xptr->vftbl->class;
pss = class_resolveclassmethod(c,
- utf_new_char("printStackTrace"),
- utf_new_char("()V"),
+ utf_printStackTrace,
+ utf_void__void,
class_java_lang_Object,
false);
if (pss) {
asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
- /* this normally means, we are EXTREMLY out of memory, but may be
- any other 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. */
+
if (*exceptionptr) {
+ fprintf(stderr, "Exception while printStackTrace(): ");
utf_fprint_classname(stderr, c->name);
fprintf(stderr, "\n");
}
fflush(stderr);
/* good bye! */
- if (doexit) {
+
+ if (doexit)
exit(1);
- }
}
}
-void throw_exception()
+void throw_exception(void)
{
throw_exception_exit_intern(false);
}
-void throw_exception_exit()
+void throw_exception_exit(void)
{
throw_exception_exit_intern(true);
}
-void throw_main_exception()
+void throw_main_exception(void)
{
fprintf(stderr, "Exception in thread \"main\" ");
fflush(stderr);
}
-void throw_main_exception_exit()
+void throw_main_exception_exit(void)
{
fprintf(stderr, "Exception in thread \"main\" ");
fflush(stderr);
}
-void throw_cacao_exception_exit(char *exception, char *message)
+void throw_cacao_exception_exit(const char *exception, const char *message, ...)
{
s4 i;
char *tmp;
s4 len;
+ va_list ap;
len = strlen(exception);
- tmp = MNEW(char, len);
+ tmp = MNEW(char, len + 1);
strncpy(tmp, exception, len);
+ tmp[len] = '\0';
/* convert to classname */
- for (i = len - 1; i >= 0; i--) {
+ for (i = len - 1; i >= 0; i--)
if (tmp[i] == '/') tmp[i] = '.';
- }
fprintf(stderr, "Exception in thread \"main\" %s", tmp);
MFREE(tmp, char, len);
- if (strlen(message) > 0)
- fprintf(stderr, ": %s", message);
+ if (strlen(message) > 0) {
+ fprintf(stderr, ": ");
+
+ va_start(ap, message);
+ vfprintf(stderr, message, ap);
+ va_end(ap);
+ }
fprintf(stderr, "\n");
fflush(stderr);
/* good bye! */
+
exit(1);
}
-#if 1
-#define CREATENEW_EXCEPTION(ex) \
- return ex;
-#else
-#define CREATENEW_EXCEPTION(ex) \
- java_objectheader *newEx; \
- java_objectheader *oldexception=*exceptionptr;\
- *exceptionptr=0;\
- newEx=ex;\
- *exceptionptr=oldexception;\
- return newEx;
-#endif
+/* new_exception ***************************************************************
+
+ Creates an exception object with the given name and initalizes it.
+
+*******************************************************************************/
-java_objectheader *new_exception(char *classname)
+java_objectheader *new_exception(const char *classname)
{
- classinfo *c = class_new(utf_new_char(classname));
+ java_objectheader *o;
+ classinfo *c;
+
+ if (!(c = load_class_bootstrap(utf_new_char(classname))))
+ return *exceptionptr;
- CREATENEW_EXCEPTION(native_new_and_init(c));
+ o = native_new_and_init(c);
+
+ if (!o)
+ return *exceptionptr;
+
+ return o;
}
-java_objectheader *new_exception_message(char *classname, char *message)
+
+/* new_exception_message *******************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given char message.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_message(const char *classname,
+ const char *message)
{
- classinfo *c = class_new(utf_new_char(classname));
+ java_objectheader *o;
+ classinfo *c;
+
+ if (!(c = load_class_bootstrap(utf_new_char(classname))))
+ return *exceptionptr;
+
+ o = native_new_and_init_string(c, javastring_new_char(message));
- CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new_char(message)));
+ if (!o)
+ return *exceptionptr;
+
+ return o;
}
-java_objectheader *new_exception_throwable(char *classname, java_lang_Throwable *throwable)
+/* new_exception_throwable *****************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/Throwable exception.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_throwable(const char *classname,
+ java_lang_Throwable *throwable)
{
- classinfo *c = class_new(utf_new_char(classname));
+ java_objectheader *o;
+ classinfo *c;
+
+ if (!(c = load_class_bootstrap(utf_new_char(classname))))
+ return *exceptionptr;
+
+ o = native_new_and_init_throwable(c, throwable);
- CREATENEW_EXCEPTION(native_new_and_init_throwable(c, throwable));
+ if (!o)
+ return *exceptionptr;
+
+ return o;
}
-java_objectheader *new_exception_utfmessage(char *classname, utf *message)
+/* new_exception_utfmessage ****************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given utf message.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
{
- classinfo *c = class_new(utf_new_char(classname));
+ java_objectheader *o;
+ classinfo *c;
+
+ if (!(c = load_class_bootstrap(utf_new_char(classname))))
+ return *exceptionptr;
- CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new(message)));
+ o = native_new_and_init_string(c, javastring_new(message));
+
+ if (!o)
+ return *exceptionptr;
+
+ return o;
}
-java_objectheader *new_exception_javastring(char *classname, java_lang_String *message)
+/* new_exception_javastring ****************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/String message.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_javastring(const char *classname,
+ java_lang_String *message)
{
- classinfo *c = class_new(utf_new_char(classname));
+ java_objectheader *o;
+ classinfo *c;
+
+ if (!(c = load_class_bootstrap(utf_new_char(classname))))
+ return *exceptionptr;
+
+ o = native_new_and_init_string(c, message);
+
+ if (!o)
+ return *exceptionptr;
- CREATENEW_EXCEPTION(native_new_and_init_string(c, message));
+ return o;
}
-java_objectheader *new_exception_int(char *classname, s4 i)
+/* new_exception_int ***********************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given int value.
+
+*******************************************************************************/
+
+java_objectheader *new_exception_int(const char *classname, s4 i)
{
- classinfo *c;
+ java_objectheader *o;
+ classinfo *c;
+
+ if (!(c = load_class_bootstrap(utf_new_char(classname))))
+ return *exceptionptr;
+
+ o = native_new_and_init_int(c, i);
- c = class_new(utf_new_char(classname));
+ if (!o)
+ return *exceptionptr;
- CREATENEW_EXCEPTION(native_new_and_init_int(c, i));
+ return o;
}
*******************************************************************************/
-java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
+java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
{
- char msg[MAXLOGTEXT];
- va_list ap;
+ java_objectheader *o;
+ char *msg;
+ s4 msglen;
+ va_list ap;
- utf_sprint_classname(msg, c->name);
- sprintf(msg + strlen(msg), " (");
+ /* calculate message length */
+
+ msglen = 0;
+
+ if (c)
+ msglen += utf_strlen(c->name) + strlen(" (");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ if (c)
+ msglen += strlen(")");
+
+ msglen += strlen("0");
+
+ /* allocate a buffer */
+
+ msg = MNEW(char, msglen);
+
+ /* print message into allocated buffer */
+
+ if (c) {
+ utf_sprint_classname(msg, c->name);
+ strcat(msg, " (");
+ }
va_start(ap, message);
vsprintf(msg + strlen(msg), message, ap);
va_end(ap);
- sprintf(msg + strlen(msg), ")");
+ if (c)
+ strcat(msg, ")");
+
+ o = new_exception_message(string_java_lang_ClassFormatError, msg);
- return new_exception_message(string_java_lang_ClassFormatError, msg);
+ MFREE(msg, char, msglen);
+
+ return o;
+}
+
+
+/* new_internalerror ***********************************************************
+
+ Generates a java.lang.InternalError for the VM.
+
+*******************************************************************************/
+
+java_objectheader *new_internalerror(const char *message, ...)
+{
+ 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);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ va_start(ap, message);
+ vsprintf(msg, message, ap);
+ va_end(ap);
+
+ /* create exception object */
+
+ o = new_exception_message(string_java_lang_InternalError, msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ return o;
}
*******************************************************************************/
-java_objectheader *new_unsupportedclassversionerror(classinfo *c, char *message, ...)
+java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
{
- char msg[MAXLOGTEXT];
- va_list ap;
+ java_objectheader *o;
+ va_list ap;
+ char *msg;
+ s4 msglen;
+
+ /* calculate exception message length */
+
+ msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
utf_sprint_classname(msg, c->name);
- sprintf(msg + strlen(msg), " (");
+ strcat(msg, " (");
va_start(ap, message);
vsprintf(msg + strlen(msg), message, ap);
va_end(ap);
- sprintf(msg + strlen(msg), ")");
+ strcat(msg, ")");
+
+ /* create exception object */
+
+ o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
+ msg);
- return new_exception_message(string_java_lang_UnsupportedClassVersionError,
- msg);
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ return o;
}
*******************************************************************************/
-java_objectheader *new_verifyerror(methodinfo *m, char *message)
+java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
{
java_objectheader *o;
- char *msg;
- s4 len;
+ va_list ap;
+ char *msg;
+ s4 msglen;
+
+ useinlining = false; /* at least until sure inlining works with exceptions*/
+
+ /* calculate exception message length */
+
+ msglen = strlen("(class: ") + utf_strlen(m->class->name) +
+ strlen(", method: ") + utf_strlen(m->name) +
+ strlen(" signature: ") + utf_strlen(m->descriptor) +
+ strlen(") ") + strlen("0");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
- len = 8 + utf_strlen(m->class->name) +
- 10 + utf_strlen(m->name) +
- 13 + utf_strlen(m->descriptor) +
- 2 + strlen(message) + 1;
-
- msg = MNEW(char, len);
-
- sprintf(msg, "(class: ");
- utf_sprint(msg + strlen(msg), m->class->name);
- sprintf(msg + strlen(msg), ", method: ");
- utf_sprint(msg + strlen(msg), m->name);
- sprintf(msg + strlen(msg), ", signature: ");
- utf_sprint(msg + strlen(msg), m->descriptor);
- sprintf(msg + strlen(msg), ") %s", message);
+ strcpy(msg, "(class: ");
+ utf_strcat(msg, m->class->name);
+ strcat(msg, ", method: ");
+ utf_strcat(msg, m->name);
+ strcat(msg, " signature: ");
+ utf_strcat(msg, m->descriptor);
+ strcat(msg, ") ");
+
+ va_start(ap, message);
+ vsprintf(msg + strlen(msg), message, ap);
+ va_end(ap);
+
+ /* create exception object */
o = new_exception_message(string_java_lang_VerifyError, msg);
- MFREE(msg, u1, len);
+ /* free memory */
+
+ MFREE(msg, char, msglen);
return o;
}
/* new_arithmeticexception *****************************************************
- generates a java.lang.ArithmeticException for the jit compiler
+ Generates a java.lang.ArithmeticException for the jit compiler.
*******************************************************************************/
-java_objectheader *new_arithmeticexception()
+java_objectheader *new_arithmeticexception(void)
{
java_objectheader *e;
/* new_arrayindexoutofboundsexception ******************************************
- generates a java.lang.ArrayIndexOutOfBoundsException for the jit compiler
+ Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT
+ compiler.
*******************************************************************************/
return *exceptionptr;
s = (java_lang_String *) asm_calljavafunction(m,
- (void *) index,
+ (void *) (ptrint) index,
NULL,
NULL,
NULL);
}
+/* new_arraystoreexception *****************************************************
+
+ generates a java.lang.ArrayStoreException for the jit compiler
+
+*******************************************************************************/
+
+java_objectheader *new_arraystoreexception(void)
+{
+ java_objectheader *e;
+
+ e = new_exception(string_java_lang_ArrayStoreException);
+
+ if (!e)
+ return *exceptionptr;
+
+ return e;
+}
+
+
/* new_classcastexception ******************************************************
generates a java.lang.ClassCastException for the jit compiler
*******************************************************************************/
-java_objectheader *new_classcastexception()
+java_objectheader *new_classcastexception(void)
{
java_objectheader *e;
*******************************************************************************/
-java_objectheader *new_negativearraysizeexception()
+java_objectheader *new_negativearraysizeexception(void)
{
java_objectheader *e;
*******************************************************************************/
-java_objectheader *new_nullpointerexception()
+java_objectheader *new_nullpointerexception(void)
{
java_objectheader *e;