OSDN Git Service

2002-04-29 Gerhard Tonn <GerhardTonn@swol.de>
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
index 5bfe4e7..4db9dca 100644 (file)
@@ -1,6 +1,6 @@
 // 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.
 
@@ -21,6 +21,7 @@ details.  */
 #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>
@@ -67,6 +68,22 @@ static inline void dupx (_Jv_word *sp, int n, int x)
   
 };
 
+// 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)
@@ -182,11 +199,21 @@ static jint get4(unsigned char* loc) {
 
 #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,
@@ -291,10 +318,14 @@ _Jv_InterpMethod::run (ffi_cif* cif,
   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 ();
 
@@ -597,7 +628,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
     INSN_LABEL(invokespecial),
     INSN_LABEL(invokestatic),
     INSN_LABEL(invokeinterface),
-    0, /* op_xxxunusedxxx1, */
+    0, /* Unused.  */
     INSN_LABEL(new),
     INSN_LABEL(newarray),
     INSN_LABEL(anewarray),
@@ -615,8 +646,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
     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
@@ -953,113 +982,81 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       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;
@@ -1165,122 +1162,90 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       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;
@@ -1398,7 +1363,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_fdiv:
-      SAVE_PC;
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
@@ -1408,7 +1372,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_ddiv:
-      SAVE_PC;
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
@@ -1438,7 +1401,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_frem:
-      SAVE_PC;
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
@@ -1448,7 +1410,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_drem:
-      SAVE_PC;
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
@@ -1590,11 +1551,19 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       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:
@@ -1602,11 +1571,19 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       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:
@@ -2226,9 +2203,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_arraylength:
-      SAVE_PC;
       {
        __JArray *arr = (__JArray*)POPA();
+       NULLARRAYCHECK (arr);
        PUSHI (arr->length);
       }
       NEXT_INSN;