// interpret.cc - Code for the interpreter
-/* Copyright (C) 1999, 2000, 2001 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
This file is part of libgcj.
#include <java/lang/System.h>
#include <java/lang/String.h>
#include <java/lang/Integer.h>
+#include <java/lang/Long.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/Class.h>
#include <java/lang/reflect/Modifier.h>
#include <stdlib.h>
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+using namespace gcj;
static void throw_internal_error (char *msg)
__attribute__ ((__noreturn__));
};
+// Used to convert from floating types to integral types.
+template<typename TO, typename FROM>
+static inline TO
+convert (FROM val, TO min, TO max)
+{
+ TO ret;
+ if (val >= (FROM) max)
+ ret = max;
+ else if (val <= (FROM) min)
+ ret = min;
+ else if (val != val)
+ ret = 0;
+ else
+ ret = (TO) val;
+ return ret;
+}
#define PUSHA(V) (sp++)->o = (V)
#define PUSHI(V) (sp++)->i = (V)
#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
+#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 ();
INSN_LABEL(invokespecial),
INSN_LABEL(invokestatic),
INSN_LABEL(invokeinterface),
- 0, /* op_xxxunusedxxx1, */
+ 0, /* Unused. */
INSN_LABEL(new),
INSN_LABEL(newarray),
INSN_LABEL(anewarray),
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
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;
NEXT_INSN;
insn_fdiv:
- SAVE_PC;
{
jfloat value2 = POPF();
jfloat value1 = POPF();
NEXT_INSN;
insn_ddiv:
- SAVE_PC;
{
jdouble value2 = POPD();
jdouble value1 = POPD();
NEXT_INSN;
insn_frem:
- SAVE_PC;
{
jfloat value2 = POPF();
jfloat value1 = POPF();
NEXT_INSN;
insn_drem:
- SAVE_PC;
{
jdouble value2 = POPD();
jdouble value1 = POPD();
NEXT_INSN;
insn_f2i:
- { jint value = (jint)POPF (); PUSHI(value); }
+ {
+ using namespace java::lang;
+ jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+ PUSHI(value);
+ }
NEXT_INSN;
insn_f2l:
- { jlong value = (jlong)POPF (); PUSHL(value); }
+ {
+ using namespace java::lang;
+ jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
+ PUSHL(value);
+ }
NEXT_INSN;
insn_f2d:
NEXT_INSN;
insn_d2i:
- { jint value = (jint)POPD (); PUSHI(value); }
+ {
+ using namespace java::lang;
+ jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+ PUSHI(value);
+ }
NEXT_INSN;
insn_d2l:
- { jlong value = (jlong)POPD (); PUSHL(value); }
+ {
+ using namespace java::lang;
+ jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
+ PUSHL(value);
+ }
NEXT_INSN;
insn_d2f:
NEXT_INSN;
insn_arraylength:
- SAVE_PC;
{
__JArray *arr = (__JArray*)POPA();
+ NULLARRAYCHECK (arr);
PUSHI (arr->length);
}
NEXT_INSN;