/* 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.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: exceptions.c 8056 2007-06-10 14:49:57Z michi $
-
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <unistd.h>
#include <sys/mman.h>
#include "vm/types.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_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/logging.h"
#include "toolbox/util.h"
#include "vm/builtin.h"
#include "vm/vm.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/disass.h"
#include "vm/jit/jit.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/show.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trace.h"
#include "vmcore/class.h"
#include "vmcore/loader.h"
+#include "vmcore/method.h"
#include "vmcore/options.h"
+#include "vmcore/system.h"
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
/* for raising exceptions from native methods *********************************/
#if !defined(ENABLE_THREADS)
-java_objectheader *_no_threads_exceptionptr = NULL;
+java_object_t *_no_threads_exceptionptr = NULL;
#endif
-/* init_system_exceptions ******************************************************
+/* exceptions_get_exception ****************************************************
- Load and link exceptions used in the system.
+ Returns the current exception pointer of the current thread.
*******************************************************************************/
-bool exceptions_init(void)
+java_handle_t *exceptions_get_exception(void)
{
- int pagesize;
-
- /* mmap a memory page at address 0x0, so our hardware-exceptions
- work. */
+ java_object_t *o;
+ java_handle_t *e;
+#if defined(ENABLE_THREADS)
+ threadobject *t;
- pagesize = getpagesize();
+ t = THREADOBJECT;
+#endif
- (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+ /* Get the exception. */
- /* check if we get into trouble with our hardware-exceptions */
+ LLNI_CRITICAL_START;
- if (OFFSET(java_bytearray, data) <= EXCEPTION_HARDWARE_PATCHER)
- vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray, data), EXCEPTION_HARDWARE_PATCHER);
+#if defined(ENABLE_THREADS)
+ o = t->_exceptionptr;
+#else
+ o = _no_threads_exceptionptr;
+#endif
- /* java/lang/Throwable */
+ e = LLNI_WRAP(o);
- if (!(class_java_lang_Throwable =
- load_class_bootstrap(utf_java_lang_Throwable)) ||
- !link_class(class_java_lang_Throwable))
- return false;
+ LLNI_CRITICAL_END;
- /* java/lang/Error */
+ /* Return the exception. */
- if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
- !link_class(class_java_lang_Error))
- return false;
+ return e;
+}
-#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
+/* exceptions_set_exception ****************************************************
- /* java/lang/NoClassDefFoundError */
+ Sets the exception pointer of the current thread.
- if (!(class_java_lang_NoClassDefFoundError =
- load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
- !link_class(class_java_lang_NoClassDefFoundError))
- return false;
+*******************************************************************************/
- /* java/lang/OutOfMemoryError */
+void exceptions_set_exception(java_handle_t *e)
+{
+ threadobject *t;
+ java_object_t *o;
- if (!(class_java_lang_OutOfMemoryError =
- load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
- !link_class(class_java_lang_OutOfMemoryError))
- return false;
+#if defined(ENABLE_THREADS)
+ t = THREADOBJECT;
+#else
+ t = NULL;
+#endif
- /* java/lang/VirtualMachineError */
+ /* Set the exception. */
- if (!(class_java_lang_VirtualMachineError =
- load_class_bootstrap(utf_java_lang_VirtualMachineError)) ||
- !link_class(class_java_lang_VirtualMachineError))
- return false;
+ LLNI_CRITICAL_START;
+ o = LLNI_UNWRAP(e);
- /* java/lang/Exception */
+#if !defined(NDEBUG)
+ if (opt_DebugExceptions) {
+ printf("[exceptions_set_exception : t=%p, o=%p, class=",
+ (void *) t, (void *) o);
+ class_print(o->vftbl->clazz);
+ printf("]\n");
+ }
+#endif
- if (!(class_java_lang_Exception =
- load_class_bootstrap(utf_java_lang_Exception)) ||
- !link_class(class_java_lang_Exception))
- return false;
+#if defined(ENABLE_THREADS)
+ t->_exceptionptr = o;
+#else
+ _no_threads_exceptionptr = o;
+#endif
- /* java/lang/ClassCastException */
+ LLNI_CRITICAL_END;
+}
- if (!(class_java_lang_ClassCastException =
- load_class_bootstrap(utf_java_lang_ClassCastException)) ||
- !link_class(class_java_lang_ClassCastException))
- return false;
- /* java/lang/ClassNotFoundException */
+/* exceptions_clear_exception **************************************************
- if (!(class_java_lang_ClassNotFoundException =
- load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
- !link_class(class_java_lang_ClassNotFoundException))
- return false;
+ Clears the current exception pointer of the current thread.
- /* java/lang/NullPointerException */
+*******************************************************************************/
- if (!(class_java_lang_NullPointerException =
- load_class_bootstrap(utf_java_lang_NullPointerException)) ||
- !link_class(class_java_lang_NullPointerException))
- return false;
+void exceptions_clear_exception(void)
+{
+ threadobject *t;
+#if defined(ENABLE_THREADS)
+ t = THREADOBJECT;
+#else
+ t = NULL;
+#endif
-#if defined(WITH_CLASSPATH_GNU)
- /* java/lang/VMThrowable */
+ /* Set the exception. */
- if (!(class_java_lang_VMThrowable =
- load_class_bootstrap(utf_java_lang_VMThrowable)) ||
- !link_class(class_java_lang_VMThrowable))
- return false;
+#if !defined(NDEBUG)
+ if (opt_DebugExceptions) {
+ printf("[exceptions_clear_exception: t=%p]\n", (void *) t);
+ }
#endif
- return true;
+#if defined(ENABLE_THREADS)
+ t->_exceptionptr = NULL;
+#else
+ _no_threads_exceptionptr = NULL;
+#endif
}
-/* exceptions_new_class ********************************************************
-
- Creates an exception object from the given class and initalizes it.
+/* exceptions_get_and_clear_exception ******************************************
- IN:
- class....class pointer
+ Gets the exception pointer of the current thread and clears it.
+ This function may return NULL.
*******************************************************************************/
-static java_objectheader *exceptions_new_class(classinfo *c)
+java_handle_t *exceptions_get_and_clear_exception(void)
{
- java_objectheader *o;
+ java_handle_t *o;
- o = native_new_and_init(c);
+ /* Get the exception... */
- if (o == NULL)
- return *exceptionptr;
+ o = exceptions_get_exception();
+
+ /* ...and clear the exception if it is set. */
+
+ if (o != NULL)
+ exceptions_clear_exception();
+
+ /* return the exception */
return o;
}
-/* exceptions_new_utf **********************************************************
+/* exceptions_abort ************************************************************
- Creates an exception object with the given name and initalizes it.
+ Prints exception to be thrown and aborts.
IN:
- classname....class name in UTF-8
+ classname....class name
+ message......exception message
*******************************************************************************/
-static java_objectheader *exceptions_new_utf(utf *classname)
+static void exceptions_abort(utf *classname, utf *message)
{
- classinfo *c;
- java_objectheader *o;
+ log_println("exception thrown while VM is initializing: ");
- c = load_class_bootstrap(classname);
+ log_start();
+ utf_display_printable_ascii_classname(classname);
- if (c == NULL)
- return *exceptionptr;
+ if (message != NULL) {
+ log_print(": ");
+ utf_display_printable_ascii_classname(message);
+ }
- o = exceptions_new_class(c);
+ log_finish();
- return o;
+ vm_abort("Aborting...");
}
-/* exceptions_throw_class ******************************************************
+/* exceptions_new_class_utf ****************************************************
- Creates an exception object from the given class, initalizes and
- throws it.
+ Creates an exception object with the given class and initalizes it
+ with the given utf message.
IN:
- class....class pointer
+ 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 void exceptions_throw_class(classinfo *c)
+static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
{
- java_objectheader *o;
+ java_handle_t *s;
+ java_handle_t *o;
+
+ if (vm_initializing) {
+ /* This can happen when global class variables are used which
+ are not initialized yet. */
+
+ if (c == NULL)
+ exceptions_abort(NULL, message);
+ else
+ exceptions_abort(c->name, message);
+ }
+
+ s = javastring_new(message);
- o = exceptions_new_class(c);
+ if (s == NULL)
+ return exceptions_get_exception();
+
+ o = native_new_and_init_string(c, s);
if (o == NULL)
- return;
+ return exceptions_get_exception();
- *exceptionptr = o;
+ return o;
}
-/* exceptions_throw_utf ********************************************************
+/* exceptions_new_utf **********************************************************
- Creates an exception object with the given name, initalizes and
- throws it.
+ Creates an exception object with the given name and initalizes it.
IN:
classname....class name in UTF-8
*******************************************************************************/
-static void exceptions_throw_utf(utf *classname)
+static java_handle_t *exceptions_new_utf(utf *classname)
{
- classinfo *c;
+ classinfo *c;
+ java_handle_t *o;
+
+ if (vm_initializing)
+ exceptions_abort(classname, NULL);
c = load_class_bootstrap(classname);
if (c == NULL)
- return;
+ return exceptions_get_exception();
- exceptions_throw_class(c);
+ o = native_new_and_init(c);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
}
-/* exceptions_throw_utf_throwable **********************************************
+/* exceptions_new_utf_javastring ***********************************************
Creates an exception object with the given name and initalizes it
- with the given java/lang/Throwable exception.
+ with the given java/lang/String message.
IN:
classname....class name in UTF-8
- cause........the given Throwable
+ 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 void exceptions_throw_utf_throwable(utf *classname,
- java_objectheader *cause)
+static java_handle_t *exceptions_new_utf_javastring(utf *classname,
+ java_handle_t *message)
{
- java_objectheader *o;
- classinfo *c;
+ java_handle_t *o;
+ classinfo *c;
+ if (vm_initializing)
+ exceptions_abort(classname, NULL);
+
c = load_class_bootstrap(classname);
if (c == NULL)
- return;
+ return exceptions_get_exception();
- o = native_new_and_init_throwable(c, cause);
+ o = native_new_and_init_string(c, message);
if (o == NULL)
- return;
+ return exceptions_get_exception();
- *exceptionptr = o;
+ return o;
}
-/* exceptions_throw_utf_exception **********************************************
+/* exceptions_new_utf_utf ******************************************************
Creates an exception object with the given name and initalizes it
- with the given java/lang/Exception exception.
+ with the given utf message.
IN:
classname....class name in UTF-8
- exception....the given Exception
+ 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 void exceptions_throw_utf_exception(utf *classname,
- java_objectheader *exception)
+static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
{
- java_objectheader *o;
- classinfo *c;
-
+ classinfo *c;
+ java_handle_t *o;
+
+ if (vm_initializing)
+ exceptions_abort(classname, message);
+
c = load_class_bootstrap(classname);
if (c == NULL)
- return;
+ 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.
- o = native_new_and_init_exception(c, exception);
+ 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
+ throws it.
+
+ IN:
+ classname....class name in UTF-8
+
+*******************************************************************************/
+
+static void exceptions_throw_utf(utf *classname)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf(classname);
if (o == NULL)
return;
- *exceptionptr = o;
+ exceptions_set_exception(o);
}
-/* exceptions_new_utf_javastring ***********************************************
+/* exceptions_throw_utf_throwable **********************************************
Creates an exception object with the given name and initalizes it
- with the given java/lang/String message.
+ with the given java/lang/Throwable exception.
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).
+ cause........the given Throwable
*******************************************************************************/
-static java_objectheader *exceptions_new_utf_javastring(utf *classname,
- java_objectheader *message)
+static void exceptions_throw_utf_throwable(utf *classname,
+ java_handle_t *cause)
{
- java_objectheader *o;
- classinfo *c;
-
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
+ java_lang_Throwable *object;
+
+ if (vm_initializing)
+ exceptions_abort(classname, NULL);
+
+ object = (java_lang_Throwable *) cause;
+
c = load_class_bootstrap(classname);
if (c == NULL)
- return *exceptionptr;
+ return;
- o = native_new_and_init_string(c, message);
+ /* create object */
+ o = builtin_new(c);
+
if (o == NULL)
- return *exceptionptr;
+ return;
- return o;
+ /* 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);
}
-/* exceptions_new_class_utf ****************************************************
+/* exceptions_throw_utf_exception **********************************************
- Creates an exception object of the given class and initalizes it.
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/Exception exception.
IN:
- c..........class pointer
- message....the message as UTF-8 string
+ classname....class name in UTF-8
+ exception....the given Exception
*******************************************************************************/
-static java_objectheader *exceptions_new_class_utf(classinfo *c, utf *message)
+static void exceptions_throw_utf_exception(utf *classname,
+ java_handle_t *exception)
{
- java_objectheader *o;
- java_objectheader *s;
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
- s = javastring_new(message);
+ if (vm_initializing)
+ exceptions_abort(classname, NULL);
- if (s == NULL)
- return *exceptionptr;
+ c = load_class_bootstrap(classname);
- o = native_new_and_init_string(c, s);
+ if (c == NULL)
+ return;
+
+ /* create object */
+ o = builtin_new(c);
+
if (o == NULL)
- return *exceptionptr;
+ return;
- return o;
+ /* 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);
}
-/* exceptions_new_utf_utf ******************************************************
+/* exceptions_throw_utf_cause **************************************************
Creates an exception object with the given name and initalizes it
- with the given utf message.
+ with the given java/lang/Throwable exception with initCause.
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).
+ cause........the given Throwable
*******************************************************************************/
-static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message)
+static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
{
- classinfo *c;
- java_objectheader *o;
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
+ java_lang_String *s;
+ java_lang_Throwable *object;
+
+ if (vm_initializing)
+ exceptions_abort(classname, NULL);
+
+ object = (java_lang_Throwable *) cause;
c = load_class_bootstrap(classname);
if (c == NULL)
- return *exceptionptr;
+ return;
- o = exceptions_new_class_utf(c, message);
+ /* create object */
- return o;
-}
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return;
+ /* call initializer */
-/* exceptions_throw_class_utf **************************************************
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
- Creates an exception object of the given class, initalizes and
- throws it with the given utf message.
+ LLNI_field_get_ref(object, detailMessage, s);
- IN:
- c..........class pointer
- message....the message as an UTF-8
+ (void) vm_call_method(m, o, s);
-*******************************************************************************/
+ /* call initCause */
-static void exceptions_throw_class_utf(classinfo *c, utf *message)
-{
- *exceptionptr = exceptions_new_class_utf(c, message);
+ m = class_resolveclassmethod(c,
+ utf_initCause,
+ utf_java_lang_Throwable__java_lang_Throwable,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, o, cause);
+
+ exceptions_set_exception(o);
}
static void exceptions_throw_utf_utf(utf *classname, utf *message)
{
- *exceptionptr = exceptions_new_utf_utf(classname, message);
+ java_handle_t *o;
+
+ o = exceptions_new_utf_utf(classname, message);
+
+ exceptions_set_exception(o);
}
*******************************************************************************/
-java_objectheader *exceptions_new_abstractmethoderror(void)
+java_handle_t *exceptions_new_abstractmethoderror(void)
{
- java_objectheader *o;
+ java_handle_t *o;
o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
*******************************************************************************/
#if defined(ENABLE_JAVAME_CLDC1_1)
-static java_objectheader *exceptions_new_error(utf *message)
+static java_handle_t *exceptions_new_error(utf *message)
{
- java_objectheader *o;
+ java_handle_t *o;
- o = exceptions_new_class_utf(class_java_lang_Error, message);
+ o = exceptions_new_utf_utf(utf_java_lang_Error, message);
return o;
}
*******************************************************************************/
-java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
+java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
{
- stackframeinfo sfi;
- java_objectheader *e;
+ stackframeinfo_t sfi;
+ java_handle_t *e;
+ java_object_t *o;
- /* create the stackframeinfo (XPC is equal to RA) */
+ /* Fill and add a stackframeinfo (XPC is equal to RA). */
- stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
+ stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra);
/* create the exception */
e = exceptions_new_error(utf_java_lang_AbstractMethodError);
#endif
- /* remove the stackframeinfo */
+ /* Remove the stackframeinfo. */
- stacktrace_remove_stackframeinfo(&sfi);
+ stacktrace_stackframeinfo_remove(&sfi);
- return e;
+ /* unwrap the exception */
+ /* ATTENTION: do the this _after_ the stackframeinfo was removed */
+
+ o = LLNI_UNWRAP(e);
+
+ return o;
}
*******************************************************************************/
-java_objectheader *exceptions_new_arraystoreexception(void)
+java_handle_t *exceptions_new_arraystoreexception(void)
{
- java_objectheader *o;
+ java_handle_t *o;
o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
*******************************************************************************/
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);
}
void exceptions_throw_noclassdeffounderror(utf *name)
{
- if (vm_initializing)
- vm_abort("java.lang.NoClassDefFoundError: %s", name->text);
+ exceptions_throw_utf_utf(utf_java_lang_NoClassDefFoundError, name);
+}
+
+
+/* exceptions_throw_noclassdeffounderror_cause *********************************
+
+ Generates and throws a java.lang.NoClassDefFoundError with the
+ given cause.
- exceptions_throw_class_utf(class_java_lang_NoClassDefFoundError, name);
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause)
+{
+ exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
}
Generates and throws a java.lang.NoClassDefFoundError with a
specific message:
-
-
IN:
name.........name of the class not found as a utf *
}
-/* classnotfoundexception_to_noclassdeffounderror ******************************
-
- Check the *exceptionptr for a ClassNotFoundException. If it is one,
- convert it to a NoClassDefFoundError.
-
-*******************************************************************************/
-
-void classnotfoundexception_to_noclassdeffounderror(void)
-{
- java_objectheader *xptr;
- java_objectheader *cause;
- java_lang_Throwable *t;
- java_objectheader *s;
-
- /* get the cause */
-
- cause = *exceptionptr;
-
- /* convert ClassNotFoundException's to NoClassDefFoundError's */
-
- if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
- /* clear exception, because we are calling jit code again */
-
- *exceptionptr = NULL;
-
- /* create new error */
-
- t = (java_lang_Throwable *) cause;
- s = (java_objectheader *) t->detailMessage;
-
- xptr = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
- s);
-
- /* we had an exception while creating the error */
-
- if (*exceptionptr)
- return;
-
- /* set new exception */
-
- *exceptionptr = xptr;
- }
-}
-
-
/* exceptions_throw_exceptionininitializererror ********************************
Generates and throws a java.lang.ExceptionInInitializerError for
*******************************************************************************/
-void exceptions_throw_exceptionininitializererror(java_objectheader *cause)
+void exceptions_throw_exceptionininitializererror(java_handle_t *cause)
{
exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
cause);
void exceptions_throw_linkageerror(const char *message, classinfo *c)
{
- java_objectheader *o;
- char *msg;
- s4 msglen;
+ utf *u;
+ char *msg;
+ int len;
/* calculate exception message length */
- msglen = strlen(message) + 1;
+ len = strlen(message) + 1;
if (c != NULL)
- msglen += utf_bytes(c->name);
+ len += utf_bytes(c->name);
/* allocate memory */
- msg = MNEW(char, msglen);
+ msg = MNEW(char, len);
/* generate message */
- strcpy(msg,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));
+ u = utf_new_char(msg);
/* free memory */
- MFREE(msg, char, msglen);
-
- if (o == NULL)
- return;
+ MFREE(msg, char, len);
- *exceptionptr = o;
+ exceptions_throw_utf_utf(utf_java_lang_LinkageError, u);
}
#if defined(ENABLE_JAVASE)
exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
#else
- exceptions_throw_class_utf(class_java_lang_Error, u);
+ exceptions_throw_utf_utf(utf_java_lang_Error, u);
#endif
}
void exceptions_throw_outofmemoryerror(void)
{
- exceptions_throw_class(class_java_lang_OutOfMemoryError);
+ exceptions_throw_utf(utf_java_lang_OutOfMemoryError);
}
#if defined(ENABLE_JAVASE)
exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
#else
- exceptions_throw_class_utf(class_java_lang_Error, name);
+ exceptions_throw_utf_utf(utf_java_lang_Error, name);
#endif
}
if (m != NULL)
msglen =
- strlen("(class: ") + utf_bytes(m->class->name) +
+ strlen("(class: ") + utf_bytes(m->clazz->name) +
strlen(", method: ") + utf_bytes(m->name) +
strlen(" signature: ") + utf_bytes(m->descriptor) +
strlen(") ") + strlen("0");
if (m != NULL) {
strcpy(msg, "(class: ");
- utf_cat_classname(msg, m->class->name);
+ utf_cat_classname(msg, m->clazz->name);
strcat(msg, ", method: ");
utf_cat(msg, m->name);
strcat(msg, " signature: ");
msglen = 0;
if (m != NULL)
- msglen = strlen("(class: ") + utf_bytes(m->class->name) +
+ msglen = strlen("(class: ") + utf_bytes(m->clazz->name) +
strlen(", method: ") + utf_bytes(m->name) +
strlen(" signature: ") + utf_bytes(m->descriptor) +
strlen(") Expecting to find longest-------typename on stack")
if (m != NULL) {
strcpy(msg, "(class: ");
- utf_cat_classname(msg, m->class->name);
+ utf_cat_classname(msg, m->clazz->name);
strcat(msg, ", method: ");
utf_cat(msg, m->name);
strcat(msg, " signature: ");
*******************************************************************************/
-java_objectheader *exceptions_new_arithmeticexception(void)
+java_handle_t *exceptions_new_arithmeticexception(void)
{
- java_objectheader *o;
+ java_handle_t *o;
o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
utf_division_by_zero);
*******************************************************************************/
-java_objectheader *exceptions_new_arrayindexoutofboundsexception(s4 index)
+java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index)
{
- java_objectheader *o;
- methodinfo *m;
- java_objectheader *s;
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *s;
/* convert the index into a String, like Sun does */
true);
if (m == NULL)
- return *exceptionptr;
+ return exceptions_get_exception();
s = vm_call_method(m, NULL, index);
if (s == NULL)
- return *exceptionptr;
+ return exceptions_get_exception();
o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
s);
if (o == NULL)
- return *exceptionptr;
+ return exceptions_get_exception();
return o;
}
void exceptions_throw_arraystoreexception(void)
{
exceptions_throw_utf(utf_java_lang_ArrayStoreException);
-/* e = native_new_and_init(class_java_lang_ArrayStoreException); */
}
*******************************************************************************/
-java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
+java_handle_t *exceptions_new_classcastexception(java_handle_t *o)
{
- java_objectheader *e;
- utf *classname;
+ java_handle_t *e;
+ classinfo *c;
+ utf *classname;
- classname = o->vftbl->class->name;
+ LLNI_class_get(o, c);
- e = exceptions_new_class_utf(class_java_lang_ClassCastException, classname);
+ classname = c->name;
+
+ e = exceptions_new_utf_utf(utf_java_lang_ClassCastException, classname);
return e;
}
*******************************************************************************/
-void exceptions_throw_invocationtargetexception(java_objectheader *cause)
+void exceptions_throw_invocationtargetexception(java_handle_t *cause)
{
exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
cause);
*******************************************************************************/
-java_objectheader *exceptions_new_nullpointerexception(void)
+java_handle_t *exceptions_new_nullpointerexception(void)
{
- java_objectheader *o;
+ java_handle_t *o;
- o = exceptions_new_class(class_java_lang_NullPointerException);
+ o = exceptions_new_utf(utf_java_lang_NullPointerException);
return o;
}
void exceptions_throw_nullpointerexception(void)
{
- exceptions_throw_class(class_java_lang_NullPointerException);
+ exceptions_throw_utf(utf_java_lang_NullPointerException);
}
*******************************************************************************/
-void exceptions_throw_privilegedactionexception(java_objectheader *exception)
+void exceptions_throw_privilegedactionexception(java_handle_t *exception)
{
exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
exception);
}
-/* exceptions_get_exception ****************************************************
-
- Returns the current exception pointer of the current thread.
-
-*******************************************************************************/
-
-java_objectheader *exceptions_get_exception(void)
-{
- /* return the exception */
-
- return *exceptionptr;
-}
-
-
-/* exceptions_set_exception ****************************************************
-
- Sets the exception pointer of the current thread.
-
-*******************************************************************************/
-
-void exceptions_set_exception(java_objectheader *o)
-{
- /* set the exception */
-
- *exceptionptr = o;
-}
-
-
-/* exceptions_clear_exception **************************************************
-
- Clears the current exception pointer of the current thread.
-
-*******************************************************************************/
-
-void exceptions_clear_exception(void)
-{
- /* and clear the exception */
-
- *exceptionptr = NULL;
-}
-
-
/* exceptions_fillinstacktrace *************************************************
Calls the fillInStackTrace-method of the currently thrown
*******************************************************************************/
-java_objectheader *exceptions_fillinstacktrace(void)
+java_handle_t *exceptions_fillinstacktrace(void)
{
- java_objectheader *o;
- methodinfo *m;
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
/* get exception */
- o = *exceptionptr;
- assert(o);
-
- /* clear exception */
+ o = exceptions_get_and_clear_exception();
- *exceptionptr = NULL;
+ assert(o);
/* resolve methodinfo pointer from exception object */
+ LLNI_class_get(o, c);
+
#if defined(ENABLE_JAVASE)
- m = class_resolvemethod(o->vftbl->class,
+ m = class_resolvemethod(c,
utf_fillInStackTrace,
utf_void__java_lang_Throwable);
#elif defined(ENABLE_JAVAME_CLDC1_1)
- m = class_resolvemethod(o->vftbl->class,
+ m = class_resolvemethod(c,
utf_fillInStackTrace,
utf_void__void);
#else
}
-/* 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_new_hardware_exception *******************************************
-
- Creates the correct exception for a hardware-exception thrown and
- caught by a signal handler.
-
-*******************************************************************************/
-
-java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val)
-{
- stackframeinfo sfi;
- java_objectheader *e;
- java_objectheader *o;
- s4 index;
-
- /* create stackframeinfo */
-
- stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
- switch (type) {
- case EXCEPTION_HARDWARE_NULLPOINTER:
- e = exceptions_new_nullpointerexception();
- break;
-
- case EXCEPTION_HARDWARE_ARITHMETIC:
- e = exceptions_new_arithmeticexception();
- break;
-
- case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
- index = (s4) val;
- e = exceptions_new_arrayindexoutofboundsexception(index);
- break;
-
- case EXCEPTION_HARDWARE_CLASSCAST:
- o = (java_objectheader *) val;
- e = exceptions_new_classcastexception(o);
- break;
-
- case EXCEPTION_HARDWARE_EXCEPTION:
- e = exceptions_fillinstacktrace();
- break;
-
- default:
- /* let's try to get a backtrace */
-
- codegen_get_pv_from_pc(xpc);
-
- /* if that does not work, print more debug info */
-
- log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
-
-#if SIZEOF_VOID_P == 8
- log_println("PC=0x%016lx", xpc);
-#else
- log_println("PC=0x%08x", xpc);
-#endif
-
-#if defined(ENABLE_DISASSEMBLER)
- log_println("machine instruction at PC:");
- disassinstr(xpc);
-#endif
-
- vm_abort("Exiting...");
-
- /* keep compiler happy */
-
- e = NULL;
- }
-
- /* remove stackframeinfo */
-
- stacktrace_remove_stackframeinfo(&sfi);
-
- /* return the exception object */
-
- return e;
-}
-
-
/* exceptions_handle_exception *************************************************
Try to find an exception handler for the given exception and return it.
*******************************************************************************/
#if defined(ENABLE_JIT)
-u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
+void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
{
- 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_objectheader *o;
+ java_object_t *o;
#endif
+ 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
- xpc = ADDR_MASK(xpc);
+ xptr = LLNI_WRAP(xptro);
+ xpc = ADDR_MASK(xpc);
+
+ /* Fill and add a stackframeinfo (XPC is equal to RA). */
+
+ stacktrace_stackframeinfo_add(&sfi, pv, sp, xpc, xpc);
+
+ 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. */
- m = (code == NULL) ? NULL : code->m;
+ if (code == NULL) {
+ result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
+ goto exceptions_handle_exception_return;
+ }
+
+ m = code->m;
#if !defined(NDEBUG)
/* print exception trace */
- if (opt_verbose || opt_verbosecall || opt_verboseexception)
- builtin_trace_exception(xptr, m, xpc, 1);
-#endif
+ if (opt_TraceExceptions)
+ trace_exception(LLNI_DIRECT(xptr), m, xpc);
-#if defined(ENABLE_VMLOG)
+# if defined(ENABLE_VMLOG)
vmlog_cacao_throw(xptr);
+# 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))
- return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
+ 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 */
#if !defined(NDEBUG)
/* Print stacktrace of exception when caught. */
-#if defined(ENABLE_VMLOG)
+# if defined(ENABLE_VMLOG)
vmlog_cacao_catch(xptr);
-#endif
+# endif
- if (opt_verboseexception) {
+ if (opt_TraceExceptions) {
exceptions_print_exception(xptr);
- stacktrace_print_trace(xptr);
+ stacktrace_print_exception(xptr);
}
#endif
- return ex->handlerpc;
+ result = ete->handlerpc;
+ goto exceptions_handle_exception_return;
}
/* 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. */
+ /* 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;
+ 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 */
if (!(c->state & CLASS_LOADED))
/* use the methods' classloader */
if (!load_class_from_classloader(c->name,
- m->class->classloader))
- return NULL;
+ m->clazz->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))
- return NULL;
+ goto exceptions_handle_exception_return;
}
/* is the thrown exception an instance of the catch class? */
#if !defined(NDEBUG)
/* Print stacktrace of exception when caught. */
-#if defined(ENABLE_VMLOG)
+# if defined(ENABLE_VMLOG)
vmlog_cacao_catch(xptr);
-#endif
+# endif
- if (opt_verboseexception) {
+ if (opt_TraceExceptions) {
exceptions_print_exception(xptr);
- stacktrace_print_trace(xptr);
+ stacktrace_print_exception(xptr);
}
#endif
- return 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)
- /* XXX change this if we ever want to use 4-byte stackslots */
- o = *((java_objectheader **) (sp + issync - 8));
-# else
- o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
-#endif
+ o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
assert(o != NULL);
- lock_monitor_exit(o);
+ lock_monitor_exit(LLNI_QUICKWRAP(o));
}
#endif
/* none of the exceptions catch this one */
-#if defined(ENABLE_VMLOG)
+#if !defined(NDEBUG)
+# if defined(ENABLE_VMLOG)
vmlog_cacao_unwnd_method(m);
-#endif
+# endif
+
+# if defined(ENABLE_DEBUG_FILTER)
+ if (show_filters_test_verbosecall_exit(m)) {
+# endif
+
+ /* outdent the log message */
+
+ if (opt_verbosecall) {
+ if (TRACEJAVACALLINDENT)
+ TRACEJAVACALLINDENT--;
+ else
+ log_text("exceptions_handle_exception: WARNING: unmatched unindent");
+ }
+
+# if defined(ENABLE_DEBUG_FILTER)
+ }
+# endif
+#endif /* !defined(NDEBUG) */
+
+ result = NULL;
+
+exceptions_handle_exception_return:
+
+ /* Remove the stackframeinfo. */
- return NULL;
+ stacktrace_stackframeinfo_remove(&sfi);
+
+ return result;
}
#endif /* defined(ENABLE_JIT) */
*******************************************************************************/
-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;
}
#if defined(ENABLE_JAVASE)
- cause = t->cause;
+ LLNI_field_get_ref(t, cause, cause);
#endif
/* print the root exception */
- utf_display_printable_ascii_classname(t->header.vftbl->class->name);
+ LLNI_class_get(t, c);
+ utf_display_printable_ascii_classname(c->name);
- if (t->detailMessage != NULL) {
- u = javastring_toutf((java_objectheader *) t->detailMessage, false);
+ LLNI_field_get_ref(t, detailMessage, s);
+
+ if (s != NULL) {
+ u = javastring_toutf((java_handle_t *) s, false);
printf(": ");
utf_display_printable_ascii(u);
if ((cause != NULL) && (cause != t)) {
printf("Caused by: ");
- utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
+
+ LLNI_class_get(cause, c);
+ utf_display_printable_ascii_classname(c->name);
- if (cause->detailMessage != NULL) {
- u = javastring_toutf((java_objectheader *) cause->detailMessage,
- false);
+ LLNI_field_get_ref(cause, detailMessage, s);
+
+ if (s != NULL) {
+ u = javastring_toutf((java_handle_t *) s, false);
printf(": ");
utf_display_printable_ascii(u);
void exceptions_print_current_exception(void)
{
- java_objectheader *xptr;
+ java_handle_t *o;
- xptr = *exceptionptr;
+ o = exceptions_get_exception();
- exceptions_print_exception(xptr);
+ exceptions_print_exception(o);
}
void exceptions_print_stacktrace(void)
{
- java_objectheader *oxptr;
- java_objectheader *xptr;
- classinfo *c;
- methodinfo *m;
+ java_handle_t *e;
+ java_handle_t *ne;
+ classinfo *c;
+ methodinfo *m;
- /* get original exception */
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+ java_lang_Thread *to;
+#endif
- oxptr = *exceptionptr;
+ /* Get and clear exception because we are calling Java code
+ again. */
- if (oxptr == NULL)
- vm_abort("exceptions_print_stacktrace: no exception thrown");
+ e = exceptions_get_and_clear_exception();
- /* clear exception, because we are calling jit code again */
+ if (e == NULL)
+ return;
- *exceptionptr = NULL;
+#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. */
- c = oxptr->vftbl->class;
+ LLNI_class_get(e, 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 compatibility message */
+ /* Print message. */
- fprintf(stderr, "Exception in thread \"main\" ");
+ fprintf(stderr, "Exception ");
- /* print the stacktrace */
+#if defined(ENABLE_THREADS)
+ /* Print thread name. We get the thread here explicitly as we
+ need it afterwards. */
- (void) vm_call_method(m, oxptr);
+ t = thread_get_current();
+ to = (java_lang_Thread *) thread_get_object(t);
- /* 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 (to != NULL) {
+ fprintf(stderr, "in thread \"");
+ thread_fprint_name(t, stderr);
+ fprintf(stderr, "\" ");
+ }
+#endif
- xptr = *exceptionptr;
+ /* Print the stacktrace. */
- if (xptr != NULL) {
- fprintf(stderr, "Exception while printStackTrace(): ");
+ if (builtin_instanceof(e, class_java_lang_Throwable)) {
+ (void) vm_call_method(m, e);
- /* now print original exception */
+ /* If this happens we are EXTREMLY out of memory or have a
+ serious problem while printStackTrace. But may be
+ another exception, so print it. */
- exceptions_print_exception(xptr);
- stacktrace_print_trace(xptr);
+ ne = exceptions_get_exception();
- /* now print original exception */
+ if (ne != NULL) {
+ fprintf(stderr, "Exception while printStackTrace(): ");
- fprintf(stderr, "Original exception was: ");
- exceptions_print_exception(oxptr);
- stacktrace_print_trace(oxptr);
- }
+ /* Print the current exception. */
+
+ exceptions_print_exception(ne);
+ stacktrace_print_exception(ne);
- fflush(stderr);
+ /* Now print the original exception. */
+
+ fprintf(stderr, "Original exception was: ");
+ exceptions_print_exception(e);
+ stacktrace_print_exception(e);
+ }
+ }
+ else {
+ fprintf(stderr, ". Uncaught exception of type ");
+#if !defined(NDEBUG)
+ /* FIXME This prints to stdout. */
+ class_print(c);
+#else
+ fprintf(stderr, "UNKNOWN");
+#endif
+ fprintf(stderr, ".");
+ }
+
+ fflush(stderr);
+ }
}