OSDN Git Service

2002-04-29 Gerhard Tonn <GerhardTonn@swol.de>
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
index 7ea7cbf..4db9dca 100644 (file)
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999  Cygnus Solutions
+/* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -14,17 +14,15 @@ details.  */
 
 #pragma implementation "java-interp.h"
 
-#include <cni.h>
 #include <jvm.h>
-#include <java-field.h>
 #include <java-cpool.h>
 #include <java-interp.h>
-#include <java/lang/fdlibm.h>
+// #include <java/lang/fdlibm.h>
 #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/io/PrintStream.h>
 #include <java/lang/Class.h>
 #include <java/lang/reflect/Modifier.h>
 #include <java/lang/ClassCastException.h>
@@ -36,51 +34,22 @@ details.  */
 #include <java-insns.h>
 #include <java-signal.h>
 
-#ifndef INTERPRETER
+#ifdef INTERPRETER
 
-#include <gnu/gcj/runtime/MethodInvocation.h>
+#include <stdlib.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;
-
-static const int PUBLIC       = 0x001;
-static const int PRIVATE      = 0x002;
-static const int PROTECTED    = 0x004;
-static const int STATIC       = 0x008;
-static const int FINAL        = 0x010;
-static const int SYNCHRONIZED = 0x020;
-static const int VOLATILE     = 0x040;
-static const int TRANSIENT    = 0x080;
-static const int NATIVE       = 0x100;
-static const int INTERFACE    = 0x200;
-static const int ABSTRACT     = 0x400;
-static const int ALL_FLAGS    = 0x7FF; 
-
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+using namespace gcj;
 
 static void throw_internal_error (char *msg)
   __attribute__ ((__noreturn__));
 static void throw_incompatible_class_change_error (jstring msg)
   __attribute__ ((__noreturn__));
-#if !HANDLE_SEGV
+#ifndef HANDLE_SEGV
 static void throw_null_pointer_exception ()
   __attribute__ ((__noreturn__));
 #endif
-#if !HANDLE_FPE
-static void throw_arithmetic_exception ()
-  __attribute__ ((__noreturn__));
-#endif
 
+extern "C" double __ieee754_fmod (double,double);
 
 static inline void dupx (_Jv_word *sp, int n, int x)
 {
@@ -99,45 +68,80 @@ 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)
 #define PUSHF(V)  (sp++)->f = (V)
-#define PUSHL(V)  ({ _Jv_word2 w2; w2.l=(V); \
-                     (sp++)->ia[0] = w2.ia[0]; \
-                     (sp++)->ia[0] = w2.ia[1]; })
-#define PUSHD(V)  ({ _Jv_word2 w2; w2.d=(V); \
-                     (sp++)->ia[0] = w2.ia[0]; \
-                     (sp++)->ia[0] = w2.ia[1]; })
+#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)  ({ jint __idx = (I); \
-    (sp++)->ia[0] = locals[__idx].ia[0]; \
-    (sp++)->ia[0] = locals[__idx+1].ia[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) ({ jint __idx = (I); \
-    locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    locals[__idx].ia[0] = (--sp)->ia[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
@@ -193,19 +197,23 @@ static jint get4(unsigned char* loc) {
 }
 
 
-#if HANDLE_SEGV
+#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
 
-#if 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,
@@ -225,15 +233,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...
     {
@@ -294,23 +309,23 @@ _Jv_InterpMethod::run (ffi_cif* cif,
        default:
          throw_internal_error ("unknown return type");
        }
-
     }
 
   /** handle an exception */
   if ( find_exception (ex, inv) )
     goto next_segment;
 
-  java::lang::System::out->println 
-    (_Jv_NewStringUTF (self->name->data));
-
   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 ();
 
@@ -349,11 +364,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,
@@ -366,14 +381,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,
@@ -386,24 +401,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);
 }
 
 /*
@@ -418,22 +423,18 @@ gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
 */
 
 
-#ifdef __i386__
-#define PC_REGISTER_ASM  asm("%esi")
-#else
-#define PC_REGISTER_ASM
-#endif
-
 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 {
-  register _Jv_word      *sp                  = inv->sp;
-  register unsigned char *pc PC_REGISTER_ASM  = inv->pc;
-  _Jv_word               *locals              = inv->local_base ();
+  using namespace java::lang::reflect;
+
+  _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
@@ -627,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),
@@ -643,36 +644,8 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
     INSN_LABEL(ifnonnull),
     INSN_LABEL(goto_w),
     INSN_LABEL(jsr_w),
-
-    INSN_LABEL(putfield_1),
-    INSN_LABEL(putfield_2),
-    INSN_LABEL(putfield_4),
-    INSN_LABEL(putfield_8),
-    INSN_LABEL(putfield_a),
-
-    INSN_LABEL(putstatic_1),
-    INSN_LABEL(putstatic_2),
-    INSN_LABEL(putstatic_4),
-    INSN_LABEL(putstatic_8),
-    INSN_LABEL(putstatic_a),
-
-    INSN_LABEL(getfield_1),
-    INSN_LABEL(getfield_2s),
-    INSN_LABEL(getfield_2u),
-    INSN_LABEL(getfield_4),
-    INSN_LABEL(getfield_8),
-    INSN_LABEL(getfield_a),
-
-    INSN_LABEL(getstatic_1),
-    INSN_LABEL(getstatic_2s),
-    INSN_LABEL(getstatic_2u),
-    INSN_LABEL(getstatic_4),
-    INSN_LABEL(getstatic_8),
-    INSN_LABEL(getstatic_a),
   };
 
-#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
@@ -688,7 +661,9 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 
 #ifdef  INLINE_SWITCH
 
-#define NEXT_INSN GOTO_INSN(*pc++)
+#define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
+
+
   NEXT_INSN;
 #else
 
@@ -711,30 +686,10 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       LOADI (get1u (pc++));
       NEXT_INSN;
 
-     insn_getfield_4:          // 0xd8
-      SAVE_PC;
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jint*) ((char*)obj + field_offset));
-      }
-      NEXT_INSN;
-
      insn_iload_1:             // 0x1b
       LOADI (1);
       NEXT_INSN;
 
-     insn_getfield_a:          // 0xda
-      SAVE_PC;
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHA(*(jobject*) ((char*)obj + field_offset));
-      }
-      NEXT_INSN;
-
      insn_invokevirtual:       // 0xb6
       SAVE_PC;
       {
@@ -749,19 +704,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->get_method(rmeth->vtable_index);
          }
       }
       goto perform_invoke;
@@ -774,7 +733,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;
 
@@ -1017,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;
@@ -1145,7 +1078,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       NEXT_INSN;
 
      insn_astore:
-      STOREI (get1u (pc++));
+      STOREA (get1u (pc++));
       NEXT_INSN;
 
      insn_istore_0:
@@ -1229,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;
@@ -1446,8 +1347,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;
@@ -1457,29 +1357,24 @@ 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;
 
      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);
       }
@@ -1489,9 +1384,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;
@@ -1501,29 +1395,24 @@ 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;
 
      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);
       }
@@ -1662,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:
@@ -1674,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:
@@ -1996,12 +1901,11 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
      insn_getstatic:
       SAVE_PC;
       {
-       unsigned char *base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
 
-       if ((field->flags & STATIC) == 0)
+       if ((field->flags & Modifier::STATIC) == 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field no longer static"));
 
@@ -2012,91 +1916,85 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
            switch (type->size_in_bytes)
              {
              case 1:
-               *base_pc = op_getstatic_1;
+               PUSHI (*(jbyte*) (field->u.addr));
                break;
 
              case 2:
                if (type == JvPrimClass (char))
-                 *base_pc = op_getstatic_2u;
+                 PUSHI(*(jchar*) (field->u.addr));
                else
-                 *base_pc = op_getstatic_2s;
+                 PUSHI(*(jshort*) (field->u.addr));
                break;
 
              case 4:
-               *base_pc = op_getstatic_4;
+               PUSHI(*(jint*) (field->u.addr));
                break;
 
              case 8:
-               *base_pc = op_getstatic_8;
+               PUSHL(*(jlong*) (field->u.addr));
                break;
              }
          }
        else
          {
-           *base_pc = op_getstatic_a;
+           PUSHA(*(jobject*) (field->u.addr));
          }
-
-       pc = base_pc;
       }
       NEXT_INSN;
 
      insn_getfield:
       SAVE_PC;
       {
-       unsigned char *base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
 
-       if ((field->flags & STATIC) != 0)
+       if ((field->flags & Modifier::STATIC) != 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field is static"));
 
        jclass type = field->type;
+       jint field_offset = field->u.boffset;
+       if (field_offset > 0xffff)
+         throw new java::lang::VirtualMachineError;
+
+       jobject obj   = POPA();
+       NULLCHECK(obj);
 
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes)
              {
              case 1:
-               *base_pc = op_getfield_1;
+               PUSHI (*(jbyte*) ((char*)obj + field_offset));
                break;
 
              case 2:
                if (type == JvPrimClass (char))
-                 *base_pc = op_getfield_2u;
+                 PUSHI (*(jchar*) ((char*)obj + field_offset));
                else
-                 *base_pc = op_getfield_2s;
+                 PUSHI (*(jshort*) ((char*)obj + field_offset));
                break;
 
              case 4:
-               *base_pc = op_getfield_4;
+               PUSHI (*(jint*) ((char*)obj + field_offset));
                break;
 
              case 8:
-               *base_pc = op_getfield_8;
+               PUSHL(*(jlong*) ((char*)obj + field_offset));
                break;
              }
          }
        else
          {
-           *base_pc = op_getfield_a;
+           PUSHA(*(jobject*) ((char*)obj + field_offset));
          }
-
-       if (field->u.boffset > 0xffff)
-         JvThrow (new java::lang::VirtualMachineError);
-
-       base_pc[1] = (field->u.boffset>>8) & 0xff;
-       base_pc[2] = field->u.boffset & 0xff;
-
-       pc = base_pc;
       }
       NEXT_INSN;
 
      insn_putstatic:
       SAVE_PC;
       {
-       unsigned char* base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
@@ -2104,41 +2002,48 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
        jclass type = field->type;
 
        // ResolvePoolEntry cannot check this
-       if ((field->flags & STATIC) == 0)
+       if ((field->flags & Modifier::STATIC) == 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field no longer static"));
 
-       /* if this is patented, then maybe we could install
-          a function in the constant pool, to do the right thing */
-
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes) 
              {
              case 1:
-               *base_pc = op_putstatic_1;
-               break;
+               {
+                 jint value = POPI();
+                 *(jbyte*) (field->u.addr) = value;
+                 break;
+               }
 
              case 2:
-               *base_pc = op_putstatic_2;
-               break;
+               {
+                 jint value = POPI();
+                 *(jchar*) (field->u.addr) = value;
+                 break;
+               }
 
              case 4:
-               *base_pc = op_putstatic_4;
-               break;
+               {
+                 jint value = POPI();
+                 *(jint*) (field->u.addr) = value;
+                 break;
+               }
 
              case 8:
-               *base_pc = op_putstatic_8;
-               break;
+               {
+                 jlong value = POPL();
+                 *(jlong*) (field->u.addr) = value;
+                 break;
+               }
              }
          }
        else
          {
-           *base_pc = op_putstatic_a;
+           jobject value = POPA();
+           *(jobject*) (field->u.addr) = value;
          }
-
-       // do the instruction again!
-       pc = base_pc;
       }
       NEXT_INSN;
 
@@ -2146,240 +2051,68 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
      insn_putfield:
       SAVE_PC;
       {
-       unsigned char* base_pc = pc-1;
        jint fieldref_index = get2u (pc); pc += 2;
        _Jv_ResolvePoolEntry (defining_class, fieldref_index);
        _Jv_Field *field = pool_data[fieldref_index].field;
 
        jclass type = field->type;
 
-       if ((field->flags & STATIC) != 0)
+       if ((field->flags & Modifier::STATIC) != 0)
          throw_incompatible_class_change_error 
            (JvNewStringLatin1 ("field is static"));
 
+       jint field_offset = field->u.boffset;
+       if (field_offset > 0xffff)
+         throw new java::lang::VirtualMachineError;
+
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes) 
              {
              case 1:
-               *base_pc = op_putfield_1;
-               break;
+               {
+                 jint    value = POPI();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jbyte*) ((char*)obj + field_offset) = value;
+                 break;
+               }
 
              case 2:
-               *base_pc = op_putfield_2;
-               break;
+               {
+                 jint    value = POPI();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jchar*) ((char*)obj + field_offset) = value;
+                 break;
+               }
 
              case 4:
-               *base_pc = op_putfield_4;
-               break;
+               {
+                 jint    value = POPI();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jint*) ((char*)obj + field_offset) = value;
+                 break;
+               }
 
              case 8:
-               *base_pc = op_putfield_8;
-               break;
+               {
+                 jlong   value = POPL();
+                 jobject obj   = POPA();
+                 NULLCHECK(obj);
+                 *(jlong*) ((char*)obj + field_offset) = value;
+                 break;
+               }
              }
          }
        else
          {
-           *base_pc = op_putfield_a;
+           jobject value = POPA();
+           jobject obj   = POPA();
+           NULLCHECK(obj);
+           *(jobject*) ((char*)obj + field_offset) = value;
          }
-
-       if (field->u.boffset > 0xffff)
-         JvThrow (new java::lang::VirtualMachineError);
-
-       base_pc[1] = (field->u.boffset>>8) & 0xff;
-       base_pc[2] = field->u.boffset & 0xff;
-
-       // do the instruction again!
-       pc = base_pc;
-      }
-      NEXT_INSN;
-
-
-     insn_getfield_1:
-      SAVE_PC;
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jbyte*) ((char*)obj + field_offset));
-      }
-      NEXT_INSN;
-
-     insn_getfield_2s:
-      SAVE_PC;
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jshort*) ((char*)obj + field_offset));
-      }
-      NEXT_INSN;
-
-     insn_getfield_2u:
-      SAVE_PC;
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHI (*(jchar*) ((char*)obj + field_offset));
-      }
-      NEXT_INSN;
-
-     insn_getfield_8:
-      SAVE_PC;
-      {
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       PUSHL(*(jlong*) ((char*)obj + field_offset));
-      }
-      NEXT_INSN;
-
-     insn_getstatic_1:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI (*(jbyte*) (field->u.addr));
-      }
-      NEXT_INSN;
-
-     insn_getstatic_2s:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI(*(jshort*) (field->u.addr));
-      }
-      NEXT_INSN;
-
-     insn_getstatic_2u:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI(*(jchar*) (field->u.addr));
-      }
-      NEXT_INSN;
-
-     insn_getstatic_4:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHI(*(jint*) (field->u.addr));
-      }
-      NEXT_INSN;
-
-     insn_getstatic_8:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHL(*(jlong*) (field->u.addr));
-      }
-      NEXT_INSN;
-
-     insn_getstatic_a:
-      {
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       PUSHA(*(jobject*) (field->u.addr));
-      }
-      NEXT_INSN;
-
-     insn_putfield_1:
-      SAVE_PC;
-      {
-       jint    value = POPI();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jbyte*) ((char*)obj + field_offset) = value;
-      }
-      NEXT_INSN;
-
-     insn_putfield_2:
-      SAVE_PC;
-      {
-       jint    value = POPI();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jchar*) ((char*)obj + field_offset) = value;
-      }
-      NEXT_INSN;
-
-     insn_putfield_4:
-      SAVE_PC;
-      {
-       jint    value = POPI();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jint*) ((char*)obj + field_offset) = value;
-      }
-      NEXT_INSN;
-
-     insn_putfield_8:
-      SAVE_PC;
-      {
-       jlong   value = POPL();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jlong*) ((char*)obj + field_offset) = value;
-      }
-      NEXT_INSN;
-
-     insn_putfield_a:
-      SAVE_PC;
-      {
-       jobject value = POPA();
-       jobject obj   = POPA();
-       NULLCHECK(obj);
-       jint field_offset = get2u (pc); pc += 2;
-       *(jobject*) ((char*)obj + field_offset) = value;
-      }
-      NEXT_INSN;
-
-     insn_putstatic_1:
-      {
-       jint    value = POPI();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jbyte*) (field->u.addr) = value;
-      }
-      NEXT_INSN;
-
-     insn_putstatic_2:
-      {
-       jint    value = POPI();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jchar*) (field->u.addr) = value;
-      }
-      NEXT_INSN;
-
-     insn_putstatic_4:
-      {
-       jint    value = POPI();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jint*) (field->u.addr) = value;
-      }
-      NEXT_INSN;
-
-     insn_putstatic_8:
-      {
-       jlong    value = POPL();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jlong*) (field->u.addr) = value;
-      }
-      NEXT_INSN;
-
-     insn_putstatic_a:
-      {
-       jobject value = POPA();
-       jint fieldref_index = get2u (pc); pc += 2;
-       _Jv_Field *field = pool_data[fieldref_index].field;
-       *(jobject*) (field->u.addr) = value;
       }
       NEXT_INSN;
 
@@ -2392,9 +2125,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;
 
@@ -2408,7 +2141,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;
 
@@ -2423,11 +2156,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);
@@ -2469,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;
@@ -2480,7 +2214,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       SAVE_PC;
       {
        jobject value = POPA();
-       JvThrow (value);
+       throw static_cast<jthrowable>(value);
       }
       NEXT_INSN;
 
@@ -2493,8 +2227,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);
@@ -2620,7 +2353,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--)
          {
@@ -2655,16 +2388,16 @@ 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);
 }
 
-#if !HANDLE_SEGV
+#ifndef HANDLE_SEGV
 static java::lang::NullPointerException *null_pointer_exc;
 static void 
 throw_null_pointer_exception ()
@@ -2672,22 +2405,8 @@ throw_null_pointer_exception ()
   if (null_pointer_exc == NULL)
     null_pointer_exc = new java::lang::NullPointerException;
 
-  JvThrow (null_pointer_exc);
-}
-#endif
-
-#if !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