/* src/vm/exceptions.c - exception related functions
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Thalinger
-
- Changes: Edwin Steiner
-
- $Id: exceptions.c 3893 2005-12-06 20:18:01Z twisti $
+ $Id: exceptions.c 8178 2007-07-05 11:13:20Z michi $
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
#include "vm/types.h"
+#include "md-abi.h"
+
#include "mm/memory.h"
+
+#include "native/jni.h"
#include "native/native.h"
+
#include "native/include/java_lang_String.h"
#include "native/include/java_lang_Throwable.h"
+
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
+
#include "toolbox/logging.h"
#include "toolbox/util.h"
-#include "vm/class.h"
+
+#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
#include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
#include "vm/jit/jit.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
/* for raising exceptions from native methods *********************************/
-#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
+#if !defined(ENABLE_THREADS)
java_objectheader *_no_threads_exceptionptr = NULL;
#endif
bool exceptions_init(void)
{
+#if !(defined(__ARM__) && defined(__LINUX__))
+ /* On arm-linux the first memory page can't be mmap'ed, as it
+ contains the exception vectors. */
+
+ int pagesize;
+
+ /* mmap a memory page at address 0x0, so our hardware-exceptions
+ work. */
+
+ pagesize = getpagesize();
+
+ (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+#endif
+
+ /* check if we get into trouble with our hardware-exceptions */
+
+ if (OFFSET(java_bytearray, data) <= EXCEPTION_HARDWARE_LARGEST)
+ vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray, data), EXCEPTION_HARDWARE_LARGEST);
+
/* java/lang/Throwable */
if (!(class_java_lang_Throwable =
!link_class(class_java_lang_Throwable))
return false;
-
- /* java/lang/VMThrowable */
-
- if (!(class_java_lang_VMThrowable =
- load_class_bootstrap(utf_java_lang_VMThrowable)) ||
- !link_class(class_java_lang_VMThrowable))
- return false;
-
-
/* java/lang/Error */
if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
!link_class(class_java_lang_Error))
return false;
- /* java/lang/NoClassDefFoundError */
-
- if (!(class_java_lang_NoClassDefFoundError =
- load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
- !link_class(class_java_lang_NoClassDefFoundError))
- return false;
-
+#if defined(ENABLE_JAVASE)
/* java/lang/LinkageError */
if (!(class_java_lang_LinkageError =
load_class_bootstrap(utf_java_lang_LinkageError)) ||
!link_class(class_java_lang_LinkageError))
return false;
+#endif
- /* java/lang/NoSuchMethodError */
+ /* java/lang/NoClassDefFoundError */
- if (!(class_java_lang_NoSuchMethodError =
- load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
- !link_class(class_java_lang_NoSuchMethodError))
+ if (!(class_java_lang_NoClassDefFoundError =
+ load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
+ !link_class(class_java_lang_NoClassDefFoundError))
return false;
/* java/lang/OutOfMemoryError */
!link_class(class_java_lang_OutOfMemoryError))
return false;
+ /* java/lang/VirtualMachineError */
+
+ if (!(class_java_lang_VirtualMachineError =
+ load_class_bootstrap(utf_java_lang_VirtualMachineError)) ||
+ !link_class(class_java_lang_VirtualMachineError))
+ return false;
+
/* java/lang/Exception */
!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 =
!link_class(class_java_lang_ClassNotFoundException))
return false;
- /* java/lang/IllegalArgumentException */
-
- if (!(class_java_lang_IllegalArgumentException =
- load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
- !link_class(class_java_lang_IllegalArgumentException))
- return false;
-
- /* java/lang/IllegalMonitorStateException */
-
- if (!(class_java_lang_IllegalMonitorStateException =
- load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
- !link_class(class_java_lang_IllegalMonitorStateException))
- return false;
-
/* java/lang/NullPointerException */
if (!(class_java_lang_NullPointerException =
return false;
- return true;
-}
+#if defined(WITH_CLASSPATH_GNU)
+ /* java/lang/VMThrowable */
+ if (!(class_java_lang_VMThrowable =
+ load_class_bootstrap(utf_java_lang_VMThrowable)) ||
+ !link_class(class_java_lang_VMThrowable))
+ return false;
+#endif
-static void throw_exception_exit_intern(bool doexit)
-{
- java_objectheader *xptr;
- classinfo *c;
- methodinfo *pss;
+ return true;
+}
- xptr = *exceptionptr;
- if (xptr) {
- /* clear exception, because we are calling jit code again */
- *exceptionptr = NULL;
+/* exceptions_get_exception ****************************************************
- c = xptr->vftbl->class;
+ Returns the current exception pointer of the current thread.
- pss = class_resolveclassmethod(c,
- utf_printStackTrace,
- utf_void__void,
- class_java_lang_Object,
- false);
+*******************************************************************************/
- /* print the stacktrace */
- if (pss) {
- asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
+java_objectheader *exceptions_get_exception(void)
+{
+ /* return the 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. */
+ return *exceptionptr;
+}
- if (*exceptionptr) {
- java_lang_Throwable *t;
- t = (java_lang_Throwable *) *exceptionptr;
+/* exceptions_set_exception ****************************************************
- fprintf(stderr, "Exception while printStackTrace(): ");
- utf_fprint_classname(stderr, t->header.vftbl->class->name);
+ Sets the exception pointer of the current thread.
- if (t->detailMessage) {
- char *buf;
+*******************************************************************************/
- buf = javastring_tochar((java_objectheader *) t->detailMessage);
- fprintf(stderr, ": %s", buf);
- MFREE(buf, char, strlen(buf));
- }
-
- fprintf(stderr, "\n");
- }
+void exceptions_set_exception(java_objectheader *o)
+{
+ /* set the exception */
- } else {
- utf_fprint_classname(stderr, c->name);
- fprintf(stderr, ": printStackTrace()V not found!\n");
- }
+ *exceptionptr = o;
+}
- fflush(stderr);
- /* good bye! */
+/* exceptions_clear_exception **************************************************
- if (doexit)
- exit(1);
- }
-}
+ Clears the current exception pointer of the current thread.
+*******************************************************************************/
-void throw_exception(void)
+void exceptions_clear_exception(void)
{
- throw_exception_exit_intern(false);
+ exceptions_set_exception(NULL);
}
-void throw_exception_exit(void)
-{
- throw_exception_exit_intern(true);
-}
+/* exceptions_get_and_clear_exception ******************************************
+ Gets the exception pointer of the current thread and clears it.
+ This function may return NULL.
-void throw_main_exception(void)
-{
- fprintf(stderr, "Exception in thread \"main\" ");
- fflush(stderr);
+*******************************************************************************/
- throw_exception_exit_intern(false);
-}
+java_objectheader *exceptions_get_and_clear_exception(void)
+{
+ java_objectheader *o;
+ /* get the exception */
-void throw_main_exception_exit(void)
-{
- fprintf(stderr, "Exception in thread \"main\" ");
- fflush(stderr);
+ o = exceptions_get_exception();
- throw_exception_exit_intern(true);
-}
+ /* and clear the exception */
+ exceptions_clear_exception();
-void throw_cacao_exception_exit(const char *exception, const char *message, ...)
-{
- s4 i;
- char *tmp;
- s4 len;
- va_list ap;
+ /* return the exception */
- len = strlen(exception);
- tmp = MNEW(char, len + 1);
- strncpy(tmp, exception, len);
- tmp[len] = '\0';
+ return o;
+}
- /* convert to classname */
- for (i = len - 1; i >= 0; i--)
- if (tmp[i] == '/') tmp[i] = '.';
+/* exceptions_new_class ********************************************************
- fprintf(stderr, "Exception in thread \"main\" %s", tmp);
+ Creates an exception object from the given class and initalizes it.
- MFREE(tmp, char, len);
+ IN:
+ class....class pointer
- if (strlen(message) > 0) {
- fprintf(stderr, ": ");
+*******************************************************************************/
- va_start(ap, message);
- vfprintf(stderr, message, ap);
- va_end(ap);
- }
+static java_objectheader *exceptions_new_class(classinfo *c)
+{
+ java_objectheader *o;
- fprintf(stderr, "\n");
- fflush(stderr);
+ o = native_new_and_init(c);
- /* good bye! */
+ if (o == NULL)
+ return exceptions_get_exception();
- exit(1);
+ return o;
}
-/* exceptions_throw_outofmemory_exit *******************************************
+/* exceptions_new_utf **********************************************************
+
+ Creates an exception object with the given name and initalizes it.
- Just print an: java.lang.InternalError: Out of memory
+ IN:
+ classname....class name in UTF-8
*******************************************************************************/
-void exceptions_throw_outofmemory_exit(void)
+static java_objectheader *exceptions_new_utf(utf *classname)
{
- throw_cacao_exception_exit(string_java_lang_InternalError,
- "Out of memory");
+ classinfo *c;
+ java_objectheader *o;
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = exceptions_new_class(c);
+
+ return o;
}
-/* new_exception ***************************************************************
+/* exceptions_throw_class ******************************************************
- Creates an exception object with the given name and initalizes it.
+ Creates an exception object from the given class, initalizes and
+ throws it.
+
+ IN:
+ class....class pointer
*******************************************************************************/
-java_objectheader *new_exception(const char *classname)
+static void exceptions_throw_class(classinfo *c)
{
java_objectheader *o;
- classinfo *c;
-
- if (!(c = load_class_bootstrap(utf_new_char(classname))))
- return *exceptionptr;
- o = native_new_and_init(c);
+ o = exceptions_new_class(c);
- if (!o)
- return *exceptionptr;
+ if (o == NULL)
+ return;
- return o;
+ exceptions_set_exception(o);
}
-/* new_exception_message *******************************************************
+/* exceptions_throw_utf ********************************************************
- Creates an exception object with the given name and initalizes it
- with the given char message.
+ Creates an exception object with the given name, initalizes and
+ throws it.
+
+ IN:
+ classname....class name in UTF-8
*******************************************************************************/
-java_objectheader *new_exception_message(const char *classname,
- const char *message)
+static void exceptions_throw_utf(utf *classname)
{
- java_objectheader *o;
- classinfo *c;
-
- if (!(c = load_class_bootstrap(utf_new_char(classname))))
- return *exceptionptr;
+ classinfo *c;
- o = native_new_and_init_string(c, javastring_new_char(message));
+ c = load_class_bootstrap(classname);
- if (!o)
- return *exceptionptr;
+ if (c == NULL)
+ return;
- return o;
+ exceptions_throw_class(c);
}
-/* new_exception_throwable *****************************************************
+/* exceptions_throw_utf_throwable **********************************************
Creates an exception object with the given name and initalizes it
with the given java/lang/Throwable exception.
+ IN:
+ classname....class name in UTF-8
+ cause........the given Throwable
+
*******************************************************************************/
-java_objectheader *new_exception_throwable(const char *classname,
- java_lang_Throwable *throwable)
+static void exceptions_throw_utf_throwable(utf *classname,
+ java_objectheader *cause)
{
- java_objectheader *o;
- classinfo *c;
-
- if (!(c = load_class_bootstrap(utf_new_char(classname))))
- return *exceptionptr;
+ classinfo *c;
+ java_objectheader *o;
+ methodinfo *m;
+ java_lang_Throwable *object;
- o = native_new_and_init_throwable(c, throwable);
+ object = (java_lang_Throwable *) cause;
- if (!o)
- return *exceptionptr;
+ c = load_class_bootstrap(classname);
- return o;
+ if (c == NULL)
+ return;
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return;
+
+ /* call initializer */
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_Throwable__void,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, o, cause);
+
+ exceptions_set_exception(o);
}
-/* new_exception_utfmessage ****************************************************
+/* exceptions_throw_utf_exception **********************************************
Creates an exception object with the given name and initalizes it
- with the given utf message.
+ with the given java/lang/Exception exception.
+
+ IN:
+ classname....class name in UTF-8
+ exception....the given Exception
*******************************************************************************/
-java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
+static void exceptions_throw_utf_exception(utf *classname,
+ java_objectheader *exception)
{
- java_objectheader *o;
classinfo *c;
-
- if (!(c = load_class_bootstrap(utf_new_char(classname))))
- return *exceptionptr;
+ java_objectheader *o;
+ methodinfo *m;
- o = native_new_and_init_string(c, javastring_new(message));
+ c = load_class_bootstrap(classname);
- if (!o)
- return *exceptionptr;
+ if (c == NULL)
+ return;
- return o;
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return;
+
+ /* call initializer */
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_Exception__V,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, o, exception);
+
+ exceptions_set_exception(o);
}
-/* new_exception_javastring ****************************************************
+/* exceptions_throw_utf_cause **************************************************
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 with initCause.
+
+ IN:
+ classname....class name in UTF-8
+ cause........the given Throwable
*******************************************************************************/
-java_objectheader *new_exception_javastring(const char *classname,
- java_lang_String *message)
+static void exceptions_throw_utf_cause(utf *classname, java_objectheader *cause)
{
- java_objectheader *o;
- classinfo *c;
-
- if (!(c = load_class_bootstrap(utf_new_char(classname))))
- return *exceptionptr;
+ classinfo *c;
+ java_objectheader *o;
+ methodinfo *m;
+ java_lang_Throwable *object;
- o = native_new_and_init_string(c, message);
+ object = (java_lang_Throwable *) cause;
- if (!o)
- return *exceptionptr;
+ c = load_class_bootstrap(classname);
- return o;
+ if (c == NULL)
+ return;
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return;
+
+ /* call initializer */
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, o, object->detailMessage);
+
+ /* call initCause */
+
+ 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);
}
-/* new_exception_int ***********************************************************
+/* exceptions_new_utf_javastring ***********************************************
Creates an exception object with the given name and initalizes it
- with the given int value.
+ 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).
*******************************************************************************/
-java_objectheader *new_exception_int(const char *classname, s4 i)
+static java_objectheader *exceptions_new_utf_javastring(utf *classname,
+ java_objectheader *message)
{
java_objectheader *o;
classinfo *c;
- if (!(c = load_class_bootstrap(utf_new_char(classname))))
- return *exceptionptr;
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
- o = native_new_and_init_int(c, i);
+ o = native_new_and_init_string(c, message);
- if (!o)
- return *exceptionptr;
+ if (o == NULL)
+ return exceptions_get_exception();
return o;
}
-/* new_classformaterror ********************************************************
+/* exceptions_new_class_utf ****************************************************
+
+ Creates an exception object of the given class and initalizes it.
- generates a java.lang.ClassFormatError for the classloader
+ IN:
+ c..........class pointer
+ message....the message as UTF-8 string
*******************************************************************************/
-java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
+static java_objectheader *exceptions_new_class_utf(classinfo *c, utf *message)
{
java_objectheader *o;
- char *msg;
- s4 msglen;
- va_list ap;
+ java_objectheader *s;
- /* calculate message length */
+ s = javastring_new(message);
- msglen = 0;
+ if (s == NULL)
+ return exceptions_get_exception();
- if (c)
- msglen += utf_strlen(c->name) + strlen(" (");
+ o = native_new_and_init_string(c, s);
- va_start(ap, message);
- msglen += get_variable_message_length(message, ap);
- va_end(ap);
+ if (o == NULL)
+ return exceptions_get_exception();
- if (c)
- msglen += strlen(")");
+ return o;
+}
- msglen += strlen("0");
- /* allocate a buffer */
+/* exceptions_new_utf_utf ******************************************************
- msg = MNEW(char, msglen);
+ Creates an exception object with the given name and initalizes it
+ with the given utf message.
- /* print message into allocated buffer */
+ IN:
+ classname....class name in UTF-8
+ message......the message as an utf *
- if (c) {
- utf_sprint_classname(msg, c->name);
- strcat(msg, " (");
- }
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
- va_start(ap, message);
- vsprintf(msg + strlen(msg), message, ap);
- va_end(ap);
+*******************************************************************************/
- if (c)
- strcat(msg, ")");
+static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message)
+{
+ classinfo *c;
+ java_objectheader *o;
- o = new_exception_message(string_java_lang_ClassFormatError, msg);
+ c = load_class_bootstrap(classname);
- MFREE(msg, char, msglen);
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = exceptions_new_class_utf(c, message);
return o;
}
-/* new_classnotfoundexception **************************************************
+/* exceptions_throw_class_utf **************************************************
- Generates a java.lang.ClassNotFoundException for the classloader.
+ Creates an exception object of the given class, initalizes and
+ throws it with the given utf message.
+
+ IN:
+ c..........class pointer
+ message....the message as an UTF-8
*******************************************************************************/
-java_objectheader *new_classnotfoundexception(utf *name)
+static void exceptions_throw_class_utf(classinfo *c, utf *message)
{
java_objectheader *o;
- o = native_new_and_init_string(class_java_lang_ClassNotFoundException,
- javastring_new(name));
-
- if (!o)
- return *exceptionptr;
+ o = exceptions_new_class_utf(c, message);
- return o;
+ exceptions_set_exception(o);
}
-/* new_noclassdeffounderror ****************************************************
+/* exceptions_throw_utf_utf ****************************************************
+
+ Creates an exception object with the given name, initalizes and
+ throws it with the given utf message.
- Generates a java.lang.NoClassDefFoundError
+ IN:
+ classname....class name in UTF-8
+ message......the message as an utf *
*******************************************************************************/
-java_objectheader *new_noclassdeffounderror(utf *name)
+static void exceptions_throw_utf_utf(utf *classname, utf *message)
{
java_objectheader *o;
- o = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
- javastring_new(name));
+ o = exceptions_new_utf_utf(classname, message);
- if (!o)
- return *exceptionptr;
-
- return o;
+ exceptions_set_exception(o);
}
-/* classnotfoundexception_to_noclassdeffounderror ******************************
+/* exceptions_new_abstractmethoderror ****************************************
- Check the *exceptionptr for a ClassNotFoundException. If it is one,
- convert it to a NoClassDefFoundError.
+ Generates a java.lang.AbstractMethodError for the VM.
*******************************************************************************/
-void classnotfoundexception_to_noclassdeffounderror(void)
+java_objectheader *exceptions_new_abstractmethoderror(void)
{
- java_objectheader *xptr;
- java_objectheader *cause;
-
- /* get the cause */
-
- cause = *exceptionptr;
+ java_objectheader *o;
- /* convert ClassNotFoundException's to NoClassDefFoundError's */
+ o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
- if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
- /* clear exception, because we are calling jit code again */
+ return o;
+}
- *exceptionptr = NULL;
- /* create new error */
+/* exceptions_new_error ********************************************************
- xptr =
- new_exception_javastring(string_java_lang_NoClassDefFoundError,
- ((java_lang_Throwable *) cause)->detailMessage);
+ Generates a java.lang.Error for the VM.
- /* we had an exception while creating the error */
+*******************************************************************************/
- if (*exceptionptr)
- return;
+#if defined(ENABLE_JAVAME_CLDC1_1)
+static java_objectheader *exceptions_new_error(utf *message)
+{
+ java_objectheader *o;
- /* set new exception */
+ o = exceptions_new_class_utf(class_java_lang_Error, message);
- *exceptionptr = xptr;
- }
+ return o;
}
+#endif
-/* new_internalerror ***********************************************************
+/* exceptions_asm_new_abstractmethoderror **************************************
- Generates a java.lang.InternalError for the VM.
+ Generates a java.lang.AbstractMethodError for
+ asm_abstractmethoderror.
*******************************************************************************/
-java_objectheader *new_internalerror(const char *message, ...)
+java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
{
- java_objectheader *o;
- va_list ap;
- char *msg;
- s4 msglen;
+ stackframeinfo sfi;
+ java_objectheader *e;
- /* calculate exception message length */
+ /* create the stackframeinfo (XPC is equal to RA) */
- va_start(ap, message);
- msglen = get_variable_message_length(message, ap);
- va_end(ap);
+ stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
- /* allocate memory */
+ /* create the exception */
- msg = MNEW(char, msglen);
+#if defined(ENABLE_JAVASE)
+ e = exceptions_new_abstractmethoderror();
+#else
+ e = exceptions_new_error(utf_java_lang_AbstractMethodError);
+#endif
- /* generate message */
+ /* remove the stackframeinfo */
- va_start(ap, message);
- vsprintf(msg, message, ap);
- va_end(ap);
+ stacktrace_remove_stackframeinfo(&sfi);
- /* create exception object */
+ return e;
+}
- o = new_exception_message(string_java_lang_InternalError, msg);
- /* free memory */
+/* exceptions_new_arraystoreexception ******************************************
- MFREE(msg, char, msglen);
+ Generates a java.lang.ArrayStoreException for the VM.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_arraystoreexception(void)
+{
+ java_objectheader *o;
+
+ o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
return o;
}
-/* exceptions_new_linkageerror *************************************************
+/* exceptions_throw_abstractmethoderror ****************************************
- Generates a java.lang.LinkageError with an error message.
- If c != NULL, the name of c is appended to the error message.
+ Generates and throws a java.lang.AbstractMethodError for the VM.
*******************************************************************************/
-java_objectheader *exceptions_new_linkageerror(const char *message,
- classinfo *c)
+void exceptions_throw_abstractmethoderror(void)
{
- java_objectheader *o;
- char *msg;
+ exceptions_throw_utf(utf_java_lang_AbstractMethodError);
+}
+
+
+/* exceptions_throw_classcircularityerror **************************************
+
+ Generates and throws a java.lang.ClassCircularityError for the
+ classloader.
+
+ IN:
+ c....the class in which the error was found
+
+*******************************************************************************/
+
+void exceptions_throw_classcircularityerror(classinfo *c)
+{
+ exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
+}
+
+
+/* exceptions_throw_classformaterror *******************************************
+
+ Generates and throws a java.lang.ClassFormatError for the VM.
+
+ IN:
+ c............the class in which the error was found
+ message......UTF-8 format string
+
+*******************************************************************************/
+
+void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
+{
+ char *msg;
+ s4 msglen;
+ va_list ap;
+ utf *u;
+
+ /* calculate message length */
+
+ msglen = 0;
+
+ if (c != NULL)
+ msglen += utf_bytes(c->name) + strlen(" (");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ if (c != NULL)
+ msglen += strlen(")");
+
+ msglen += strlen("0");
+
+ /* allocate a buffer */
+
+ msg = MNEW(char, msglen);
+
+ /* print message into allocated buffer */
+
+ if (c != NULL) {
+ utf_copy_classname(msg, c->name);
+ strcat(msg, " (");
+ }
+
+ va_start(ap, message);
+ vsprintf(msg + strlen(msg), message, ap);
+ va_end(ap);
+
+ if (c != NULL)
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
+}
+
+
+/* exceptions_throw_classnotfoundexception *************************************
+
+ Generates and throws a java.lang.ClassNotFoundException for the
+ VM.
+
+ IN:
+ name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_classnotfoundexception(utf *name)
+{
+ /* we use class here, as this one is rather frequent */
+
+ exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
+}
+
+
+/* exceptions_throw_noclassdeffounderror ***************************************
+
+ Generates and throws a java.lang.NoClassDefFoundError.
+
+ IN:
+ name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror(utf *name)
+{
+ if (vm_initializing)
+ vm_abort("java.lang.NoClassDefFoundError: %s", name->text);
+
+ exceptions_throw_class_utf(class_java_lang_NoClassDefFoundError, name);
+}
+
+
+/* exceptions_throw_noclassdeffounderror_cause *********************************
+
+ Generates and throws a java.lang.NoClassDefFoundError with the
+ given cause.
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_cause(java_objectheader *cause)
+{
+ exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
+}
+
+
+/* exceptions_throw_noclassdeffounderror_wrong_name ****************************
+
+ Generates and throws a java.lang.NoClassDefFoundError with a
+ specific message:
+
+ IN:
+ name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
+ utf_bytes(name) + strlen(")") + strlen("0");
+
+ msg = MNEW(char, msglen);
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, " (wrong name: ");
+ utf_cat_classname(msg, name);
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_noclassdeffounderror(u);
+}
+
+
+/* exceptions_throw_exceptionininitializererror ********************************
+
+ Generates and throws a java.lang.ExceptionInInitializerError for
+ the VM.
+
+ IN:
+ cause......cause exception object
+
+*******************************************************************************/
+
+void exceptions_throw_exceptionininitializererror(java_objectheader *cause)
+{
+ exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
+ cause);
+}
+
+
+/* exceptions_throw_incompatibleclasschangeerror *******************************
+
+ Generates and throws a java.lang.IncompatibleClassChangeError for
+ the VM.
+
+ IN:
+ message......UTF-8 message format string
+
+*******************************************************************************/
+
+void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, message);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
+}
+
+
+/* exceptions_throw_instantiationerror *****************************************
+
+ Generates and throws a java.lang.InstantiationError for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_instantiationerror(classinfo *c)
+{
+ exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
+}
+
+
+/* exceptions_throw_internalerror **********************************************
+
+ Generates and throws a java.lang.InternalError for the VM.
+
+ IN:
+ message......UTF-8 message format string
+
+*******************************************************************************/
+
+void exceptions_throw_internalerror(const char *message, ...)
+{
+ va_list ap;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ va_start(ap, message);
+ msglen = get_variable_message_length(message, ap);
+ va_end(ap);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ va_start(ap, message);
+ vsprintf(msg, message, ap);
+ va_end(ap);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
+}
+
+
+/* exceptions_throw_linkageerror ***********************************************
+
+ Generates and throws java.lang.LinkageError with an error message.
+
+ IN:
+ message......UTF-8 message
+ c............class related to the error. If this is != NULL
+ the name of c is appended to the error message.
+
+*******************************************************************************/
+
+void exceptions_throw_linkageerror(const char *message, classinfo *c)
+{
+ java_objectheader *o;
+ char *msg;
s4 msglen;
/* calculate exception message length */
- msglen = strlen(message) + 1;
- if (c) {
- msglen += utf_strlen(c->name);
- }
-
- /* allocate memory */
+ msglen = strlen(message) + 1;
+
+ if (c != NULL)
+ msglen += utf_bytes(c->name);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ strcpy(msg,message);
+
+ if (c != NULL)
+ utf_cat_classname(msg, c->name);
+
+ o = native_new_and_init_string(class_java_lang_LinkageError,
+ javastring_new_from_utf_string(msg));
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ if (o == NULL)
+ return;
+
+ exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_nosuchfielderror *******************************************
+
+ Generates and throws a java.lang.NoSuchFieldError with an error
+ message.
+
+ IN:
+ c............class in which the field was not found
+ name.........name of the field
+
+*******************************************************************************/
+
+void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, ".");
+ utf_cat(msg, name);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
+}
+
+
+/* exceptions_throw_nosuchmethoderror ******************************************
+
+ Generates and throws a java.lang.NoSuchMethodError with an error
+ message.
+
+ IN:
+ c............class in which the method was not found
+ name.........name of the method
+ desc.........descriptor of the method
+
+*******************************************************************************/
+
+void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
+ utf_bytes(desc) + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, ".");
+ utf_cat(msg, name);
+ utf_cat(msg, desc);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+#if defined(ENABLE_JAVASE)
+ exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
+#else
+ exceptions_throw_class_utf(class_java_lang_Error, u);
+#endif
+}
+
+
+/* exceptions_throw_outofmemoryerror *******************************************
+
+ Generates and throws an java.lang.OutOfMemoryError for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_outofmemoryerror(void)
+{
+ exceptions_throw_class(class_java_lang_OutOfMemoryError);
+}
+
+
+/* exceptions_throw_unsatisfiedlinkerror ***************************************
+
+ Generates and throws a java.lang.UnsatisfiedLinkError for the
+ classloader.
+
+ IN:
+ name......UTF-8 name string
+
+*******************************************************************************/
+
+void exceptions_throw_unsatisfiedlinkerror(utf *name)
+{
+#if defined(ENABLE_JAVASE)
+ exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
+#else
+ exceptions_throw_class_utf(class_java_lang_Error, name);
+#endif
+}
+
+
+/* exceptions_throw_unsupportedclassversionerror *******************************
+
+ Generates and throws a java.lang.UnsupportedClassVersionError for
+ the classloader.
+
+ IN:
+ c............class in which the method was not found
+ message......UTF-8 format string
+
+*******************************************************************************/
+
+void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen =
+ utf_bytes(c->name) +
+ strlen(" (Unsupported major.minor version 00.0)") +
+ strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ utf_copy_classname(msg, c->name);
+ sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
+ ma, mi);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
+}
+
+
+/* exceptions_throw_verifyerror ************************************************
+
+ Generates and throws a java.lang.VerifyError for the JIT compiler.
+
+ IN:
+ m............method in which the error was found
+ message......UTF-8 format string
+
+*******************************************************************************/
+
+void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
+{
+ va_list ap;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = 0;
+
+ if (m != NULL)
+ msglen =
+ strlen("(class: ") + utf_bytes(m->class->name) +
+ strlen(", method: ") + utf_bytes(m->name) +
+ strlen(" signature: ") + utf_bytes(m->descriptor) +
+ strlen(") ") + strlen("0");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ if (m != NULL) {
+ strcpy(msg, "(class: ");
+ utf_cat_classname(msg, m->class->name);
+ strcat(msg, ", method: ");
+ utf_cat(msg, m->name);
+ strcat(msg, " signature: ");
+ utf_cat(msg, m->descriptor);
+ strcat(msg, ") ");
+ }
+
+ va_start(ap, message);
+ vsprintf(msg + strlen(msg), message, ap);
+ va_end(ap);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
+}
+
+
+/* exceptions_throw_verifyerror_for_stack **************************************
+
+ throws a java.lang.VerifyError for an invalid stack slot type
+
+ IN:
+ m............method in which the error was found
+ type.........the expected type
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
+{
+ char *msg;
+ s4 msglen;
+ char *typename;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = 0;
+
+ if (m != NULL)
+ msglen = strlen("(class: ") + utf_bytes(m->class->name) +
+ strlen(", method: ") + utf_bytes(m->name) +
+ strlen(" signature: ") + utf_bytes(m->descriptor) +
+ strlen(") Expecting to find longest-------typename on stack")
+ + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ if (m != NULL) {
+ strcpy(msg, "(class: ");
+ utf_cat_classname(msg, m->class->name);
+ strcat(msg, ", method: ");
+ utf_cat(msg, m->name);
+ strcat(msg, " signature: ");
+ utf_cat(msg, m->descriptor);
+ strcat(msg, ") ");
+ }
+ else {
+ msg[0] = 0;
+ }
+
+ strcat(msg, "Expecting to find ");
+
+ switch (type) {
+ case TYPE_INT: typename = "integer"; break;
+ case TYPE_LNG: typename = "long"; break;
+ case TYPE_FLT: typename = "float"; break;
+ case TYPE_DBL: typename = "double"; break;
+ case TYPE_ADR: typename = "object/array"; break;
+ case TYPE_RET: typename = "returnAddress"; break;
+ default: typename = "<INVALID>"; assert(0); break;
+ }
+
+ strcat(msg, typename);
+ strcat(msg, " on stack");
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
+}
+
+
+/* exceptions_new_arithmeticexception ******************************************
+
+ Generates a java.lang.ArithmeticException for the JIT compiler.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_arithmeticexception(void)
+{
+ java_objectheader *o;
+
+ o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
+ utf_division_by_zero);
+
+ return o;
+}
+
+
+/* exceptions_new_arrayindexoutofboundsexception *******************************
+
+ Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
+ system.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_arrayindexoutofboundsexception(s4 index)
+{
+ java_objectheader *o;
+ methodinfo *m;
+ java_objectheader *s;
+
+ /* convert the index into a String, like Sun does */
- msg = MNEW(char, msglen);
+ m = class_resolveclassmethod(class_java_lang_String,
+ utf_new_char("valueOf"),
+ utf_new_char("(I)Ljava/lang/String;"),
+ class_java_lang_Object,
+ true);
- /* generate message */
+ if (m == NULL)
+ return exceptions_get_exception();
- strcpy(msg,message);
- if (c) {
- utf_strcat(msg, c->name);
- }
+ s = vm_call_method(m, NULL, index);
- o = native_new_and_init_string(class_java_lang_LinkageError,
- javastring_new_char(msg));
+ if (s == NULL)
+ return exceptions_get_exception();
- /* free memory */
+ o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
+ s);
- MFREE(msg, char, msglen);
+ if (o == NULL)
+ return exceptions_get_exception();
return o;
}
-/* exceptions_new_nosuchmethoderror ********************************************
+/* exceptions_throw_arrayindexoutofboundsexception *****************************
- Generates a java.lang.NoSuchMethodError with an error message.
+ Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
+ the VM.
*******************************************************************************/
-java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
- utf *name, utf *desc)
+void exceptions_throw_arrayindexoutofboundsexception(void)
{
- java_objectheader *o;
- char *msg;
- s4 msglen;
+ exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
+}
- /* calculate exception message length */
- msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
- utf_strlen(desc) + strlen("0");
+/* exceptions_throw_arraystoreexception ****************************************
- /* allocate memory */
+ Generates and throws a java.lang.ArrayStoreException for the VM.
- msg = MNEW(char, msglen);
+*******************************************************************************/
- /* generate message */
+void exceptions_throw_arraystoreexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_ArrayStoreException);
+/* e = native_new_and_init(class_java_lang_ArrayStoreException); */
+}
- utf_sprint(msg, c->name);
- strcat(msg, ".");
- utf_strcat(msg, name);
- utf_strcat(msg, desc);
- o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
- javastring_new_char(msg));
+/* exceptions_new_classcastexception *******************************************
- /* free memory */
+ Generates a java.lang.ClassCastException for the JIT compiler.
- MFREE(msg, char, msglen);
+*******************************************************************************/
- return o;
+java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
+{
+ java_objectheader *e;
+ utf *classname;
+
+ classname = o->vftbl->class->name;
+
+ e = exceptions_new_class_utf(class_java_lang_ClassCastException, classname);
+
+ return e;
}
-/* new_unsupportedclassversionerror ********************************************
+/* exceptions_throw_clonenotsupportedexception *********************************
- generates a java.lang.UnsupportedClassVersionError for the classloader
+ Generates and throws a java.lang.CloneNotSupportedException for the
+ VM.
*******************************************************************************/
-java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
+void exceptions_throw_clonenotsupportedexception(void)
{
- java_objectheader *o;
- va_list ap;
- char *msg;
- s4 msglen;
+ exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
+}
- /* calculate exception message length */
- msglen = utf_strlen(c->name) + strlen(" (") + strlen(")") + strlen("0");
+/* exceptions_throw_illegalaccessexception *************************************
- va_start(ap, message);
- msglen += get_variable_message_length(message, ap);
- va_end(ap);
+ Generates and throws a java.lang.IllegalAccessException for the VM.
- /* allocate memory */
+*******************************************************************************/
- msg = MNEW(char, msglen);
+void exceptions_throw_illegalaccessexception(utf *message)
+{
+ exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
+}
- /* generate message */
- utf_sprint_classname(msg, c->name);
- strcat(msg, " (");
+/* exceptions_throw_illegalargumentexception ***********************************
- va_start(ap, message);
- vsprintf(msg + strlen(msg), message, ap);
- va_end(ap);
+ Generates and throws a java.lang.IllegalArgumentException for the
+ VM.
- strcat(msg, ")");
+*******************************************************************************/
- /* create exception object */
+void exceptions_throw_illegalargumentexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
+}
- o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
- msg);
- /* free memory */
+/* exceptions_throw_illegalmonitorstateexception *******************************
- MFREE(msg, char, msglen);
+ Generates and throws a java.lang.IllegalMonitorStateException for
+ the VM.
- return o;
+*******************************************************************************/
+
+void exceptions_throw_illegalmonitorstateexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
}
-/* new_verifyerror *************************************************************
+/* exceptions_throw_instantiationexception *************************************
- generates a java.lang.VerifyError for the jit compiler
+ Generates and throws a java.lang.InstantiationException for the VM.
*******************************************************************************/
-java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
+void exceptions_throw_instantiationexception(classinfo *c)
{
- java_objectheader *o;
- va_list ap;
- char *msg;
- s4 msglen;
+ exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
+}
- useinlining = false; /* at least until sure inlining works with exceptions*/
- /* calculate exception message length */
+/* exceptions_throw_interruptedexception ***************************************
- msglen = 0;
+ Generates and throws a java.lang.InterruptedException for the VM.
- if (m)
- 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);
+void exceptions_throw_interruptedexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_InterruptedException);
+}
- /* allocate memory */
- msg = MNEW(char, msglen);
+/* exceptions_throw_invocationtargetexception **********************************
- /* generate message */
+ Generates and throws a java.lang.reflect.InvocationTargetException
+ for the VM.
- if (m) {
- 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, ") ");
- }
+ IN:
+ cause......cause exception object
- va_start(ap, message);
- vsprintf(msg + strlen(msg), message, ap);
- va_end(ap);
+*******************************************************************************/
- /* create exception object */
+void exceptions_throw_invocationtargetexception(java_objectheader *cause)
+{
+ exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
+ cause);
+}
- o = new_exception_message(string_java_lang_VerifyError, msg);
- /* free memory */
+/* exceptions_throw_negativearraysizeexception *********************************
- MFREE(msg, char, msglen);
+ Generates and throws a java.lang.NegativeArraySizeException for the
+ VM.
- return o;
+*******************************************************************************/
+
+void exceptions_throw_negativearraysizeexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
}
-/* new_arithmeticexception *****************************************************
+/* exceptions_new_nullpointerexception *****************************************
- Generates a java.lang.ArithmeticException for the jit compiler.
+ Generates a java.lang.NullPointerException for the VM system.
*******************************************************************************/
-java_objectheader *new_arithmeticexception(void)
+java_objectheader *exceptions_new_nullpointerexception(void)
{
- java_objectheader *e;
-
- e = new_exception_message(string_java_lang_ArithmeticException,
- string_java_lang_ArithmeticException_message);
+ java_objectheader *o;
- if (!e)
- return *exceptionptr;
+ o = exceptions_new_class(class_java_lang_NullPointerException);
- return e;
+ return o;
}
-/* new_arrayindexoutofboundsexception ******************************************
+/* exceptions_throw_nullpointerexception ***************************************
- Generates a java.lang.ArrayIndexOutOfBoundsException for the JIT
- compiler.
+ Generates a java.lang.NullPointerException for the VM system and
+ throw it in the VM system.
*******************************************************************************/
-java_objectheader *new_arrayindexoutofboundsexception(s4 index)
+void exceptions_throw_nullpointerexception(void)
{
- java_objectheader *e;
- methodinfo *m;
- java_lang_String *s;
+ exceptions_throw_class(class_java_lang_NullPointerException);
+}
- /* convert the index into a String, like Sun does */
- m = class_resolveclassmethod(class_java_lang_String,
- utf_new_char("valueOf"),
- utf_new_char("(I)Ljava/lang/String;"),
- class_java_lang_Object,
- true);
+/* exceptions_throw_privilegedactionexception **********************************
- if (!m)
- return *exceptionptr;
+ Generates and throws a java.security.PrivilegedActionException.
+
+*******************************************************************************/
- s = (java_lang_String *) asm_calljavafunction(m,
- (void *) (ptrint) index,
- NULL,
- NULL,
- NULL);
+void exceptions_throw_privilegedactionexception(java_objectheader *exception)
+{
+ exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
+ exception);
+}
- if (!s)
- return *exceptionptr;
- e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
- s);
+/* exceptions_throw_stringindexoutofboundsexception ****************************
- if (!e)
- return *exceptionptr;
+ Generates and throws a java.lang.StringIndexOutOfBoundsException
+ for the VM.
- return e;
+*******************************************************************************/
+
+void exceptions_throw_stringindexoutofboundsexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
}
-/* new_arraystoreexception *****************************************************
+/* exceptions_classnotfoundexception_to_noclassdeffounderror *******************
- generates a java.lang.ArrayStoreException for the jit compiler
+ Check the exception for a ClassNotFoundException. If it is one,
+ convert it to a NoClassDefFoundError.
*******************************************************************************/
-java_objectheader *new_arraystoreexception(void)
+void exceptions_classnotfoundexception_to_noclassdeffounderror(void)
{
- java_objectheader *e;
+ java_objectheader *o;
+ java_objectheader *cause;
+ java_lang_Throwable *object;
+ java_objectheader *s;
- e = new_exception(string_java_lang_ArrayStoreException);
-/* e = native_new_and_init(class_java_lang_ArrayStoreException); */
+ /* get the cause */
- if (!e)
- return *exceptionptr;
+ cause = exceptions_get_exception();
- return e;
-}
+ /* convert ClassNotFoundException's to NoClassDefFoundError's */
+
+ if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
+ /* clear exception, because we are calling jit code again */
+ exceptions_clear_exception();
-/* new_classcastexception ******************************************************
+ /* create new error */
- generates a java.lang.ClassCastException for the jit compiler
+ object = (java_lang_Throwable *) cause;
+ s = (java_objectheader *) object->detailMessage;
-*******************************************************************************/
+ o = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
+ s);
-java_objectheader *new_classcastexception(void)
-{
- java_objectheader *e;
+ /* we had an exception while creating the error */
- e = new_exception(string_java_lang_ClassCastException);
+ if (exceptions_get_exception())
+ return;
- if (!e)
- return *exceptionptr;
+ /* set new exception */
- return e;
+ exceptions_set_exception(o);
+ }
}
-/* new_illegalargumentexception ************************************************
+/* exceptions_fillinstacktrace *************************************************
- Generates a java.lang.IllegalArgumentException for the VM system.
+ Calls the fillInStackTrace-method of the currently thrown
+ exception.
*******************************************************************************/
-java_objectheader *new_illegalargumentexception(void)
+java_objectheader *exceptions_fillinstacktrace(void)
{
- java_objectheader *e;
+ java_objectheader *o;
+ methodinfo *m;
- if (!(e = native_new_and_init(class_java_lang_IllegalArgumentException)))
- return *exceptionptr;
+ /* get exception */
- return e;
-}
+ o = exceptions_get_and_clear_exception();
+ assert(o);
-/* new_illegalmonitorstateexception ********************************************
+ /* resolve methodinfo pointer from exception object */
- Generates a java.lang.IllegalMonitorStateException for the VM
- thread system.
+#if defined(ENABLE_JAVASE)
+ m = class_resolvemethod(o->vftbl->class,
+ utf_fillInStackTrace,
+ utf_void__java_lang_Throwable);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+ m = class_resolvemethod(o->vftbl->class,
+ utf_fillInStackTrace,
+ utf_void__void);
+#else
+#error IMPLEMENT ME!
+#endif
-*******************************************************************************/
+ /* call function */
-java_objectheader *new_illegalmonitorstateexception(void)
-{
- java_objectheader *e;
+ (void) vm_call_method(m, o);
- if (!(e = native_new_and_init(class_java_lang_IllegalMonitorStateException)))
- return *exceptionptr;
+ /* return exception object */
- return e;
+ return o;
}
-/* new_negativearraysizeexception **********************************************
+/* exceptions_new_hardware_exception *******************************************
- generates a java.lang.NegativeArraySizeException for the jit compiler
+ Creates the correct exception for a hardware-exception thrown and
+ caught by a signal handler.
*******************************************************************************/
-java_objectheader *new_negativearraysizeexception(void)
+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;
- e = new_exception(string_java_lang_NegativeArraySizeException);
+ /* create stackframeinfo */
- if (!e)
- return *exceptionptr;
+ stacktrace_create_extern_stackframeinfo(sfi, pv, sp, ra, xpc);
- return e;
-}
+ switch (type) {
+ case EXCEPTION_HARDWARE_NULLPOINTER:
+ e = exceptions_new_nullpointerexception();
+ break;
+ case EXCEPTION_HARDWARE_ARITHMETIC:
+ e = exceptions_new_arithmeticexception();
+ break;
-/* new_nullpointerexception ****************************************************
+ case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
+ index = (s4) val;
+ e = exceptions_new_arrayindexoutofboundsexception(index);
+ break;
- generates a java.lang.NullPointerException for the jit compiler
+ case EXCEPTION_HARDWARE_CLASSCAST:
+ o = (java_objectheader *) val;
+ e = exceptions_new_classcastexception(o);
+ break;
-*******************************************************************************/
+ case EXCEPTION_HARDWARE_EXCEPTION:
+ e = exceptions_fillinstacktrace();
+ break;
-java_objectheader *new_nullpointerexception(void)
-{
- java_objectheader *e;
+ case EXCEPTION_HARDWARE_PATCHER:
+ e = patcher_handler(xpc);
+ break;
+
+ default:
+ /* let's try to get a backtrace */
+
+ codegen_get_pv_from_pc(xpc);
+
+ /* if that does not work, print more debug info */
- e = native_new_and_init(class_java_lang_NullPointerException);
+ log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
- if (!e)
- return *exceptionptr;
+#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 *************************************************
- XXX
+ Try to find an exception handler for the given exception and return it.
+ If no handler is found, exit the monitor of the method (if any)
+ and return NULL.
+
+ IN:
+ xptr.........the exception object
+ xpc..........PC of where the exception was thrown
+ pv...........Procedure Value of the current method
+ sp...........current stack pointer
+
+ RETURN VALUE:
+ the address of the first matching exception handler, or
+ NULL if no handler was found
*******************************************************************************/
+#if defined(ENABLE_JIT)
u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
{
methodinfo *m;
- s4 framesize;
+ codeinfo *code;
s4 issync;
- exceptionentry *ex;
+ dseg_exception_entry *ex;
s4 exceptiontablelength;
s4 i;
classref_or_classinfo cr;
classinfo *c;
+#if defined(ENABLE_THREADS)
java_objectheader *o;
+#endif
+
+#ifdef __S390__
+ /* Addresses are 31 bit integers */
+# define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF)
+#else
+# define ADDR_MASK(x) (x)
+#endif
+
+ xpc = ADDR_MASK(xpc);
- /* get methodinfo pointer from method header */
+ /* get info from the method header */
- m = *((methodinfo **) (pv + MethodPointer));
- framesize = *((s4 *) (pv + FrameSize));
- issync = *((s4 *) (pv + IsSync));
- ex = (exceptionentry *) (pv + ExTableStart);
- exceptiontablelength = *((s4 *) (pv + ExTableSize));
+ code = *((codeinfo **) (pv + CodeinfoPointer));
+ issync = *((s4 *) (pv + IsSync));
+ ex = (dseg_exception_entry *) (pv + ExTableStart);
+ exceptiontablelength = *((s4 *) (pv + ExTableSize));
-/* if (m != NULL) { */
-/* printf("exceptions_handle_exception: "); */
-/* utf_display(m->class->name); */
-/* printf("."); */
-/* utf_display(m->name); */
-/* utf_display(m->descriptor); */
-/* printf(", %d\n", exceptiontablelength); */
-/* } */
+ /* Get the methodinfo pointer from the codeinfo pointer. For
+ asm_vm_call_method the codeinfo pointer is NULL. */
- builtin_trace_exception(xptr, m, xpc, 1);
+ m = (code == NULL) ? NULL : code->m;
+
+#if !defined(NDEBUG)
+ /* print exception trace */
+
+ if (opt_verbose || opt_verbosecall || opt_TraceExceptions)
+ builtin_trace_exception(xptr, m, xpc, 1);
+#endif
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_throw(xptr);
+#endif
for (i = 0; i < exceptiontablelength; i++) {
/* ATTENTION: keep this here, as we need to decrement the
ex--;
+ /* If the start and end PC is NULL, this means we have the
+ special case of asm_vm_call_method. So, just return the
+ proper exception handler. */
+
+ if ((ex->startpc == NULL) && (ex->endpc == NULL))
+ return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
+
/* is the xpc is the current catch range */
- if (ex->startpc <= xpc && xpc < ex->endpc) {
+ if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) {
cr = ex->catchtype;
/* NULL catches everything */
- if (cr.any == NULL)
+ if (cr.any == NULL) {
+#if !defined(NDEBUG)
+ /* Print stacktrace of exception when caught. */
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_catch(xptr);
+#endif
+
+ if (opt_TraceExceptions) {
+ exceptions_print_exception(xptr);
+ stacktrace_print_trace(xptr);
+ }
+#endif
+
return ex->handlerpc;
+ }
/* resolve or load/link the exception class */
if (IS_CLASSREF(cr)) {
+ /* The exception class reference is unresolved. */
+ /* We have to do _eager_ resolving here. While the class of */
+ /* the exception object is guaranteed to be loaded, it may */
+ /* well have been loaded by a different loader than the */
+ /* defining loader of m's class, which is the one we must */
+ /* use to resolve the catch class. Thus lazy resolving */
+ /* might fail, even if the result of the resolution would */
+ /* be an already loaded class. */
+
c = resolve_classref_eager(cr.ref);
+ if (c == NULL) {
+ /* Exception resolving the exception class, argh! */
+ return NULL;
+ }
+
+ /* Ok, we resolved it. Enter it in the table, so we don't */
+ /* have to do this again. */
+ /* XXX this write should be atomic. Is it? */
+
+ ex->catchtype.cls = c;
} else {
c = cr.cls;
+ /* XXX I don't think this case can ever happen. -Edwin */
if (!(c->state & CLASS_LOADED))
/* use the methods' classloader */
if (!load_class_from_classloader(c->name,
m->class->classloader))
return NULL;
+ /* XXX I think, if it is not linked, we can be sure that */
+ /* the exception object is no (indirect) instance of it, no? */
+ /* -Edwin */
if (!(c->state & CLASS_LINKED))
if (!link_class(c))
return NULL;
/* is the thrown exception an instance of the catch class? */
- if (builtin_instanceof(xptr, c))
+ if (builtin_instanceof(xptr, c)) {
+#if !defined(NDEBUG)
+ /* Print stacktrace of exception when caught. */
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_catch(xptr);
+#endif
+
+ if (opt_TraceExceptions) {
+ exceptions_print_exception(xptr);
+ stacktrace_print_trace(xptr);
+ }
+#endif
+
return ex->handlerpc;
+ }
}
}
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
/* is this method synchronized? */
if (issync) {
/* get synchronization object */
+# if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+ /* 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
- assert(o);
+ assert(o != NULL);
- builtin_monitorexit(o);
+ lock_monitor_exit(o);
}
#endif
/* none of the exceptions catch this one */
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_unwnd_method(m);
+#endif
+
return NULL;
}
+#endif /* defined(ENABLE_JIT) */
/* exceptions_print_exception **************************************************
void exceptions_print_exception(java_objectheader *xptr)
{
java_lang_Throwable *t;
+#if defined(ENABLE_JAVASE)
java_lang_Throwable *cause;
+#endif
utf *u;
t = (java_lang_Throwable *) xptr;
+
+ if (t == NULL) {
+ puts("NULL\n");
+ return;
+ }
+
+#if defined(ENABLE_JAVASE)
cause = t->cause;
+#endif
/* print the root exception */
- utf_display_classname(t->header.vftbl->class->name);
+ utf_display_printable_ascii_classname(t->header.vftbl->class->name);
- if (t->detailMessage) {
- u = javastring_toutf(t->detailMessage, false);
+ if (t->detailMessage != NULL) {
+ u = javastring_toutf((java_objectheader *) t->detailMessage, false);
printf(": ");
- utf_display(u);
+ utf_display_printable_ascii(u);
}
putc('\n', stdout);
+#if defined(ENABLE_JAVASE)
/* print the cause if available */
- if (cause && (cause != t)) {
+ if ((cause != NULL) && (cause != t)) {
printf("Caused by: ");
- utf_display_classname(cause->header.vftbl->class->name);
+ utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
- if (cause->detailMessage) {
- u = javastring_toutf(cause->detailMessage, false);
+ if (cause->detailMessage != NULL) {
+ u = javastring_toutf((java_objectheader *) cause->detailMessage,
+ false);
printf(": ");
- utf_display(u);
+ utf_display_printable_ascii(u);
}
putc('\n', stdout);
}
+#endif
+}
+
+
+/* exceptions_print_current_exception ******************************************
+
+ Prints the current pending exception, the detail message and the
+ cause, if available, with CACAO internal functions to stdout.
+
+*******************************************************************************/
+
+void exceptions_print_current_exception(void)
+{
+ java_objectheader *o;
+
+ o = exceptions_get_exception();
+
+ exceptions_print_exception(o);
+}
+
+
+/* exceptions_print_stacktrace *************************************************
+
+ Prints a pending exception with Throwable.printStackTrace(). If
+ there happens an exception during printStackTrace(), we print the
+ thrown exception and the original one.
+
+ NOTE: This function calls Java code.
+
+*******************************************************************************/
+
+void exceptions_print_stacktrace(void)
+{
+ java_objectheader *oxptr;
+ java_objectheader *xptr;
+ classinfo *c;
+ methodinfo *m;
+
+ /* get original exception */
+
+ oxptr = exceptions_get_and_clear_exception();
+
+ if (oxptr == NULL)
+ vm_abort("exceptions_print_stacktrace: no exception thrown");
+
+ /* clear exception, because we are calling jit code again */
+
+ c = oxptr->vftbl->class;
+
+ /* find the printStackTrace() method */
+
+ m = class_resolveclassmethod(c,
+ utf_printStackTrace,
+ utf_void__void,
+ class_java_lang_Object,
+ false);
+
+ if (m == NULL)
+ vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+
+ /* print compatibility message */
+
+ fprintf(stderr, "Exception in thread \"main\" ");
+
+ /* print the stacktrace */
+
+ (void) vm_call_method(m, oxptr);
+
+ /* This normally means, we are EXTREMLY out of memory or
+ have a serious problem while printStackTrace. But may
+ be another exception, so print it. */
+
+ xptr = exceptions_get_exception();
+
+ if (xptr != NULL) {
+ fprintf(stderr, "Exception while printStackTrace(): ");
+
+ /* now print original exception */
+
+ exceptions_print_exception(xptr);
+ stacktrace_print_trace(xptr);
+
+ /* now print original exception */
+
+ fprintf(stderr, "Original exception was: ");
+ exceptions_print_exception(oxptr);
+ stacktrace_print_trace(oxptr);
+ }
+
+ fflush(stderr);
}
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/