// interpret.cc - Code for the interpreter
-/* Copyright (C) 1999, 2000 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
This file is part of libgcj.
#ifdef INTERPRETER
-#define ClassError _CL_Q34java4lang5Error
-extern java::lang::Class ClassError;
+#include <stdlib.h>
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+using namespace gcj;
static void throw_internal_error (char *msg)
__attribute__ ((__noreturn__));
static void throw_null_pointer_exception ()
__attribute__ ((__noreturn__));
#endif
-#ifndef HANDLE_FPE
-static void throw_arithmetic_exception ()
- __attribute__ ((__noreturn__));
-#endif
-
-extern "C" double __ieee754_fmod __P((double,double));
+extern "C" double __ieee754_fmod (double,double);
static inline void dupx (_Jv_word *sp, int n, int x)
{
#ifdef HANDLE_SEGV
#define NULLCHECK(X)
+#define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)
#else
#define NULLCHECK(X) \
do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
+#define NULLARRAYCHECK(X) \
+ do { if ((X)==NULL) { SAVE_PC; throw_null_pointer_exception (); } } while (0)
#endif
-#ifdef HANDLE_FPE
-#define ZEROCHECK(X)
-#else
-#define ZEROCHECK(X) \
- do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
-#endif
+#define ARRAYBOUNDSCHECK(array, index) \
+ do \
+ { \
+ if (((unsigned) index) >= (unsigned) (array->length)) \
+ _Jv_ThrowBadArrayIndex (index); \
+ } \
+ while (0)
// this method starts the actual running of the method. It is inlined
// in three different variants in the static methods run_normal,
return ex;
}
+#define SAVE_PC inv->pc = pc
+
bool _Jv_InterpMethod::find_exception (jobject ex,
_Jv_InterpMethodInvocation *inv)
{
- int logical_pc = inv->pc - bytecode ();
+ // We subtract one because the PC was incremented before it was
+ // saved.
+ int logical_pc = inv->pc - 1 - bytecode ();
_Jv_InterpException *exc = exceptions ();
jclass exc_class = ex->getClass ();
// "run" ro be inlined. Otherwise gcc will ignore the inline directive.
int storage_size = _this->max_stack+_this->max_locals;
_Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
- alloca (sizeof (_Jv_InterpMethodInvocation)
- + storage_size * sizeof (_Jv_word));
+ __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
+ + storage_size * sizeof (_Jv_word));
jobject ex = _this->run (cif, ret, args, inv);
- if (ex != 0) _Jv_Throw (ex);
+ if (ex != 0) throw static_cast<jthrowable>(ex);
}
void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
int storage_size = _this->max_stack+_this->max_locals;
_Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
- alloca (sizeof (_Jv_InterpMethodInvocation)
- + storage_size * sizeof (_Jv_word));
+ __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
+ + storage_size * sizeof (_Jv_word));
_Jv_MonitorEnter (rcv);
jobject ex = _this->run (cif, ret, args, inv);
_Jv_MonitorExit (rcv);
- if (ex != 0) _Jv_Throw (ex);
+ if (ex != 0) throw static_cast<jthrowable>(ex);
}
void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
int storage_size = _this->max_stack+_this->max_locals;
_Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
- alloca (sizeof (_Jv_InterpMethodInvocation)
- + storage_size * sizeof (_Jv_word));
+ __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
+ + storage_size * sizeof (_Jv_word));
_Jv_MonitorEnter (sync);
jobject ex = _this->run (cif, ret, args, inv);
_Jv_MonitorExit (sync);
- if (ex != 0) _Jv_Throw (ex);
+ if (ex != 0) throw static_cast<jthrowable>(ex);
}
/*
{
using namespace java::lang::reflect;
- register _Jv_word *sp = inv->sp;
- register unsigned char *pc = inv->pc;
+ _Jv_word *sp = inv->sp;
+ unsigned char *pc = inv->pc;
_Jv_word *locals = inv->local_base ();
_Jv_word *pool_data = defining_class->constants.data;
/* these two are used in the invokeXXX instructions */
- void (*fun)(...);
+ void (*fun)();
_Jv_ResolvedMethod* rmeth;
#define INSN_LABEL(op) &&insn_##op
INSN_LABEL(jsr_w),
};
-#define SAVE_PC inv->pc = pc-1
-
/* If the macro INLINE_SWITCH is not defined, then the main loop
operates as one big (normal) switch statement. If it is defined,
then the case selection is performed `inline' in the end of the
rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
sp -= rmeth->stack_item_count;
- NULLCHECK(sp[0]);
+ // We don't use NULLCHECK here because we can't rely on that
+ // working if the method is final. So instead we do an
+ // explicit test.
+ if (! sp[0].o)
+ throw new java::lang::NullPointerException;
if (rmeth->vtable_index == -1)
{
// final methods do not appear in the vtable,
// if it does not appear in the superclass.
- fun = (void (*) (...)) rmeth->method->ncode;
+ fun = (void (*)()) rmeth->method->ncode;
}
else
{
jobject rcv = sp[0].o;
_Jv_VTable *table = *(_Jv_VTable**)rcv;
- fun = (void (*) (...))table->method[rmeth->vtable_index];
+ fun = (void (*)()) table->get_method(rmeth->vtable_index);
}
}
goto perform_invoke;
NEXT_INSN;
insn_iaload:
- SAVE_PC;
{
jint index = POPI();
jintArray arr = (jintArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHI( elements(arr)[index] );
}
NEXT_INSN;
insn_laload:
- SAVE_PC;
{
jint index = POPI();
jlongArray arr = (jlongArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHL( elements(arr)[index] );
}
NEXT_INSN;
insn_faload:
- SAVE_PC;
{
jint index = POPI();
jfloatArray arr = (jfloatArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHF( elements(arr)[index] );
}
NEXT_INSN;
insn_daload:
- SAVE_PC;
{
jint index = POPI();
jdoubleArray arr = (jdoubleArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHD( elements(arr)[index] );
}
NEXT_INSN;
insn_aaload:
- SAVE_PC;
{
jint index = POPI();
jobjectArray arr = (jobjectArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHA( elements(arr)[index] );
}
NEXT_INSN;
insn_baload:
- SAVE_PC;
{
jint index = POPI();
jbyteArray arr = (jbyteArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHI( elements(arr)[index] );
}
NEXT_INSN;
insn_caload:
- SAVE_PC;
{
jint index = POPI();
jcharArray arr = (jcharArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHI( elements(arr)[index] );
}
NEXT_INSN;
insn_saload:
- SAVE_PC;
{
jint index = POPI();
jshortArray arr = (jshortArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
PUSHI( elements(arr)[index] );
}
NEXT_INSN;
NEXT_INSN;
insn_iastore:
- SAVE_PC;
{
jint value = POPI();
jint index = POPI();
jintArray arr = (jintArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_lastore:
- SAVE_PC;
{
jlong value = POPL();
jint index = POPI();
jlongArray arr = (jlongArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_fastore:
- SAVE_PC;
{
jfloat value = POPF();
jint index = POPI();
jfloatArray arr = (jfloatArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_dastore:
- SAVE_PC;
{
jdouble value = POPD();
jint index = POPI();
jdoubleArray arr = (jdoubleArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_aastore:
- SAVE_PC;
{
jobject value = POPA();
jint index = POPI();
jobjectArray arr = (jobjectArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
_Jv_CheckArrayStore (arr, value);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_bastore:
- SAVE_PC;
{
jbyte value = (jbyte) POPI();
jint index = POPI();
jbyteArray arr = (jbyteArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_castore:
- SAVE_PC;
{
jchar value = (jchar) POPI();
jint index = POPI();
jcharArray arr = (jcharArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
insn_sastore:
- SAVE_PC;
{
jshort value = (jshort) POPI();
jint index = POPI();
jshortArray arr = (jshortArray) POPA();
- NULLCHECK (arr);
- if (index < 0 || index >= arr->length)
- {
- _Jv_ThrowBadArrayIndex (index);
- }
+ NULLARRAYCHECK (arr);
+ ARRAYBOUNDSCHECK (arr, index);
elements(arr)[index] = value;
}
NEXT_INSN;
{
jint value2 = POPI();
jint value1 = POPI();
- ZEROCHECK (value2);
- jint res = value1 / value2;
+ jint res = _Jv_divI (value1, value2);
PUSHI (res);
}
NEXT_INSN;
{
jlong value2 = POPL();
jlong value1 = POPL();
- ZEROCHECK (value2);
- jlong res = value1 / value2;
+ jlong res = _Jv_divJ (value1, value2);
PUSHL (res);
}
NEXT_INSN;
insn_fdiv:
- SAVE_PC;
{
jfloat value2 = POPF();
jfloat value1 = POPF();
- ZEROCHECK (value2);
jfloat res = value1 / value2;
PUSHF (res);
}
NEXT_INSN;
insn_ddiv:
- SAVE_PC;
{
jdouble value2 = POPD();
jdouble value1 = POPD();
- ZEROCHECK (value2);
jdouble res = value1 / value2;
PUSHD (res);
}
SAVE_PC;
{
jint value2 = POPI();
- jint value1 = POPI();
- ZEROCHECK (value2);
- jint res = value1 % value2;
+ jint value1 = POPI();
+ jint res = _Jv_remI (value1, value2);
PUSHI (res);
}
NEXT_INSN;
{
jlong value2 = POPL();
jlong value1 = POPL();
- ZEROCHECK (value2);
- jlong res = value1 % value2;
+ jlong res = _Jv_remJ (value1, value2);
PUSHL (res);
}
NEXT_INSN;
insn_frem:
- SAVE_PC;
{
jfloat value2 = POPF();
jfloat value1 = POPF();
- ZEROCHECK (value2);
jfloat res = __ieee754_fmod (value1, value2);
PUSHF (res);
}
NEXT_INSN;
insn_drem:
- SAVE_PC;
{
jdouble value2 = POPD();
jdouble value1 = POPD();
- ZEROCHECK (value2);
jdouble res = __ieee754_fmod (value1, value2);
PUSHD (res);
}
{
case 1:
PUSHI (*(jbyte*) (field->u.addr));
+ break;
case 2:
if (type == JvPrimClass (char))
jclass type = field->type;
jint field_offset = field->u.boffset;
if (field_offset > 0xffff)
- JvThrow (new java::lang::VirtualMachineError);
+ throw new java::lang::VirtualMachineError;
jobject obj = POPA();
NULLCHECK(obj);
jint field_offset = field->u.boffset;
if (field_offset > 0xffff)
- JvThrow (new java::lang::VirtualMachineError);
+ throw new java::lang::VirtualMachineError;
if (type->isPrimitive ())
{
sp -= rmeth->stack_item_count;
- NULLCHECK(sp[0]);
+ NULLCHECK (sp[0].o);
- fun = (void (*) (...))rmeth->method->ncode;
+ fun = (void (*)()) rmeth->method->ncode;
}
goto perform_invoke;
sp -= rmeth->stack_item_count;
_Jv_InitClass (rmeth->klass);
- fun = (void (*) (...))rmeth->method->ncode;
+ fun = (void (*)()) rmeth->method->ncode;
}
goto perform_invoke;
rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
sp -= rmeth->stack_item_count;
- NULLCHECK(sp[0]);
jobject rcv = sp[0].o;
- fun = (void (*) (...))
+ NULLCHECK (rcv);
+
+ fun = (void (*)())
_Jv_LookupInterfaceMethod (rcv->getClass (),
rmeth->method->name,
rmeth->method->signature);
NEXT_INSN;
insn_arraylength:
- SAVE_PC;
{
__JArray *arr = (__JArray*)POPA();
+ NULLARRAYCHECK (arr);
PUSHI (arr->length);
}
NEXT_INSN;
SAVE_PC;
{
jobject value = POPA();
- JvThrow (value);
+ throw static_cast<jthrowable>(value);
}
NEXT_INSN;
if (value != NULL && ! to->isInstance (value))
{
- JvThrow (new java::lang::ClassCastException
- (to->getName()));
+ throw new java::lang::ClassCastException (to->getName());
}
PUSHA (value);
jclass type
= (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
_Jv_InitClass (type);
- jint *sizes = (jint*) alloca (sizeof (jint)*dim);
+ jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
for (int i = dim - 1; i >= 0; i--)
{
static void
throw_internal_error (char *msg)
{
- JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
+ throw new java::lang::InternalError (JvNewStringLatin1 (msg));
}
static void
throw_incompatible_class_change_error (jstring msg)
{
- JvThrow (new java::lang::IncompatibleClassChangeError (msg));
+ throw new java::lang::IncompatibleClassChangeError (msg);
}
#ifndef HANDLE_SEGV
if (null_pointer_exc == NULL)
null_pointer_exc = new java::lang::NullPointerException;
- JvThrow (null_pointer_exc);
-}
-#endif
-
-#ifndef HANDLE_FPE
-static java::lang::ArithmeticException *arithmetic_exc;
-static void
-throw_arithmetic_exception ()
-{
- if (arithmetic_exc == NULL)
- arithmetic_exc = new java::lang::ArithmeticException
- (JvNewStringLatin1 ("/ by zero"));
-
- JvThrow (arithmetic_exc);
+ throw null_pointer_exc;
}
#endif
-
#endif // INTERPRETER