OSDN Git Service

* config/avr/avr.md (strlenhi): PARALLEL keyword removed.
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
index c8870c3..b121a1b 100644 (file)
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999, 2000  Red Hat, Inc.
+/* Copyright (C) 1999, 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -33,22 +33,9 @@ details.  */
 #include <java-insns.h>
 #include <java-signal.h>
 
-#ifndef INTERPRETER
+#ifdef INTERPRETER
 
-#include <gnu/gcj/runtime/MethodInvocation.h>
-
-/* This should never happen. */
-void 
-gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
-                                               gnu::gcj::RawData *)
-{
-  JvFail ("no interpreter");
-}
-
-#else
-
-#define ClassError _CL_Q34java4lang5Error
-extern java::lang::Class ClassError;
+#include <stdlib.h>
 
 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
 
@@ -60,13 +47,8 @@ static void throw_incompatible_class_change_error (jstring msg)
 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)
 {
@@ -89,41 +71,60 @@ static inline void dupx (_Jv_word *sp, int n, int x)
 #define PUSHA(V)  (sp++)->o = (V)
 #define PUSHI(V)  (sp++)->i = (V)
 #define PUSHF(V)  (sp++)->f = (V)
-#define PUSHL(V)  do { _Jv_word2 w2; w2.l=(V); \
-                     (sp++)->ia[0] = w2.ia[0]; \
-                     (sp++)->ia[0] = w2.ia[1]; } while (0)
-#define PUSHD(V)  do { _Jv_word2 w2; w2.d=(V); \
-                     (sp++)->ia[0] = w2.ia[0]; \
-                     (sp++)->ia[0] = w2.ia[1]; } while (0)
+#if SIZEOF_VOID_P == 8
+# define PUSHL(V)   (sp->l = (V), sp += 2)
+# define PUSHD(V)   (sp->d = (V), sp += 2)
+#else
+# define PUSHL(V)  do { _Jv_word2 w2; w2.l=(V); \
+                        (sp++)->ia[0] = w2.ia[0]; \
+                        (sp++)->ia[0] = w2.ia[1]; } while (0)
+# define PUSHD(V)  do { _Jv_word2 w2; w2.d=(V); \
+                        (sp++)->ia[0] = w2.ia[0]; \
+                        (sp++)->ia[0] = w2.ia[1]; } while (0)
+#endif
 
 #define POPA()    ((--sp)->o)
 #define POPI()    ((jint) (--sp)->i) // cast since it may be promoted
 #define POPF()    ((jfloat) (--sp)->f)
-#define POPL()    ({ _Jv_word2 w2; \
+#if SIZEOF_VOID_P == 8
+# define POPL()          (sp -= 2, (jlong) sp->l)
+# define POPD()          (sp -= 2, (jdouble) sp->d)
+#else
+# define POPL()    ({ _Jv_word2 w2; \
                      w2.ia[1] = (--sp)->ia[0]; \
                      w2.ia[0] = (--sp)->ia[0]; w2.l; })
-#define POPD()    ({ _Jv_word2 w2; \
+# define POPD()    ({ _Jv_word2 w2; \
                      w2.ia[1] = (--sp)->ia[0]; \
                      w2.ia[0] = (--sp)->ia[0]; w2.d; })
+#endif
 
 #define LOADA(I)  (sp++)->o = locals[I].o
 #define LOADI(I)  (sp++)->i = locals[I].i
 #define LOADF(I)  (sp++)->f = locals[I].f
-#define LOADL(I)  do { jint __idx = (I); \
-    (sp++)->ia[0] = locals[__idx].ia[0]; \
-    (sp++)->ia[0] = locals[__idx+1].ia[0]; \
- } while (0)
-#define LOADD(I)  LOADL(I)
-
+#if SIZEOF_VOID_P == 8
+# define LOADL(I)  (sp->l = locals[I].l, sp += 2)
+# define LOADD(I)  (sp->d = locals[I].d, sp += 2)
+#else
+# define LOADL(I)  do { jint __idx = (I); \
+                       (sp++)->ia[0] = locals[__idx].ia[0]; \
+                       (sp++)->ia[0] = locals[__idx+1].ia[0]; \
+                  } while (0)
+# define LOADD(I)  LOADL(I)
+#endif
 
 #define STOREA(I) locals[I].o = (--sp)->o
 #define STOREI(I) locals[I].i = (--sp)->i
 #define STOREF(I) locals[I].f = (--sp)->f
-#define STOREL(I) do { jint __idx = (I); \
-    locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    locals[__idx].ia[0] = (--sp)->ia[0]; \
- } while (0)
-#define STORED(I) STOREL(I)
+#if SIZEOF_VOID_P == 8
+# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
+# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+#else
+# define STOREL(I) do { jint __idx = (I); \
+                      locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+                      locals[__idx].ia[0] = (--sp)->ia[0]; \
+                  } while (0)
+# define STORED(I) STOREL(I)
+#endif
 
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
@@ -186,12 +187,6 @@ static jint get4(unsigned char* loc) {
   do { if ((X)==NULL) 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
 
 // this method starts the actual running of the method.  It is inlined
 // in three different variants in the static methods run_normal,
@@ -211,15 +206,22 @@ _Jv_InterpMethod::run (ffi_cif* cif,
   _Jv_word *locals = inv->local_base ();
 
   /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At leat, that's the idea.
+     stack representation exactly.  At least, that's the idea.
   */
   memcpy ((void*) locals, (void*) args, args_raw_size);
 
  next_segment:
-  /* this will call the method _Jv_InterpMethod::continue0, see below */
-  jobject ex = 
-    gnu::gcj::runtime::MethodInvocation::continue0
-    ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
+
+  jobject ex = NULL;
+
+  try
+    {
+      continue1 (inv);
+    }
+  catch (java::lang::Throwable *ex2)
+    {
+      ex = ex2;
+    }
 
   if (ex == 0)                 // no exception...
     {
@@ -280,7 +282,6 @@ _Jv_InterpMethod::run (ffi_cif* cif,
        default:
          throw_internal_error ("unknown return type");
        }
-
     }
 
   /** handle an exception */
@@ -332,11 +333,11 @@ void _Jv_InterpMethod::run_normal (ffi_cif* cif,
   // "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,
@@ -349,14 +350,14 @@ 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,
@@ -369,24 +370,14 @@ 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);
-}
-
-/* this is the exception handler hack, for the interpreter */
-void 
-gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
-                                               gnu::gcj::RawData *inv)
-{
-  _Jv_InterpMethod           *meth0 = (_Jv_InterpMethod*)meth;
-  _Jv_InterpMethodInvocation *inv0  = (_Jv_InterpMethodInvocation*)inv;
-  meth0->continue1 (inv0);
+  if (ex != 0) throw static_cast<jthrowable>(ex);
 }
 
 /*
@@ -405,14 +396,14 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 {
   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
@@ -684,19 +675,23 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        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->method[rmeth->vtable_index];
          }
       }
       goto perform_invoke;
@@ -709,7 +704,13 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
        jdouble rvalue;
 
+#if FFI_NATIVE_RAW_API
+       /* We assume that this is only implemented if it's correct      */
+       /* to use it here.  On a 64 bit machine, it never is.           */
        ffi_raw_call (cif, fun, (void*)&rvalue, raw);
+#else
+       ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
 
        int rtype = cif->rtype->type;
 
@@ -1080,7 +1081,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_astore:
-      STOREI (get1u (pc++));
+      STOREA (get1u (pc++));
       NEXT_INSN;
 
      insn_istore_0:
@@ -1381,8 +1382,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jint value2 = POPI();
        jint value1 = POPI();
-       ZEROCHECK (value2);
-       jint res = value1 / value2;
+       jint res = _Jv_divI (value1, value2);
        PUSHI (res);
       }
       NEXT_INSN;
@@ -1392,8 +1392,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jlong value2 = POPL();
        jlong value1 = POPL();
-       ZEROCHECK (value2);
-       jlong res = value1 / value2;
+       jlong res = _Jv_divJ (value1, value2);
        PUSHL (res);
       }
       NEXT_INSN;
@@ -1403,7 +1402,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
-       ZEROCHECK (value2);
        jfloat res = value1 / value2;
        PUSHF (res);
       }
@@ -1414,7 +1412,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
-       ZEROCHECK (value2);
        jdouble res = value1 / value2;
        PUSHD (res);
       }
@@ -1424,9 +1421,8 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       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;
@@ -1436,8 +1432,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jlong value2 = POPL();
        jlong value1 = POPL();
-       ZEROCHECK (value2);
-       jlong res = value1 % value2;
+       jlong res = _Jv_remJ (value1, value2);
        PUSHL (res);
       }
       NEXT_INSN;
@@ -1447,7 +1442,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
-       ZEROCHECK (value2);
        jfloat res    = __ieee754_fmod (value1, value2);
        PUSHF (res);
       }
@@ -1458,7 +1452,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
-       ZEROCHECK (value2);
        jdouble res    = __ieee754_fmod (value1, value2);
        PUSHD (res);
       }
@@ -1947,6 +1940,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
              {
              case 1:
                PUSHI (*(jbyte*) (field->u.addr));
+               break;
 
              case 2:
                if (type == JvPrimClass (char))
@@ -1985,7 +1979,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        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);
@@ -2092,7 +2086,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
        jint field_offset = field->u.boffset;
        if (field_offset > 0xffff)
-         JvThrow (new java::lang::VirtualMachineError);
+         throw new java::lang::VirtualMachineError;
 
        if (type->isPrimitive ())
          {
@@ -2154,9 +2148,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
        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;
 
@@ -2170,7 +2164,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        sp -= rmeth->stack_item_count;
 
        _Jv_InitClass (rmeth->klass);
-       fun = (void (*) (...))rmeth->method->ncode;
+       fun = (void (*)()) rmeth->method->ncode;
       }
       goto perform_invoke;
 
@@ -2185,11 +2179,12 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        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);
@@ -2242,7 +2237,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       SAVE_PC;
       {
        jobject value = POPA();
-       JvThrow (value);
+       throw static_cast<jthrowable>(value);
       }
       NEXT_INSN;
 
@@ -2255,8 +2250,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
        if (value != NULL && ! to->isInstance (value))
          {
-           JvThrow (new java::lang::ClassCastException
-                    (to->getName()));
+           throw new java::lang::ClassCastException (to->getName());
          }
 
        PUSHA (value);
@@ -2382,7 +2376,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        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--)
          {
@@ -2417,13 +2411,13 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 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
@@ -2434,22 +2428,8 @@ throw_null_pointer_exception ()
   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