OSDN Git Service

* passes.c (rest_of_handle_jump): Remove dead code.
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
index 5fd2c2b..0446c72 100644 (file)
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -54,6 +54,21 @@ static void throw_null_pointer_exception ()
   __attribute__ ((__noreturn__));
 #endif
 
+#ifdef DIRECT_THREADED
+// Lock to ensure that methods are not compiled concurrently.
+// We could use a finer-grained lock here, however it is not safe to use
+// the Class monitor as user code in another thread could hold it.
+static _Jv_Mutex_t compile_mutex;
+
+void
+_Jv_InitInterpreter()
+{
+  _Jv_MutexInit (&compile_mutex);
+}
+#else
+void _Jv_InitInterpreter() {}
+#endif
+
 extern "C" double __ieee754_fmod (double,double);
 
 // This represents a single slot in the "compiled" form of the
@@ -759,18 +774,25 @@ _Jv_InterpMethod::compile (const void * const *insn_targets)
 }
 #endif /* DIRECT_THREADED */
 
-// This function exists so that the stack-tracing code can find the
-// boundaries of the interpreter.
-void
-_Jv_StartOfInterpreter (void)
-{
-}
+// These exist so that the stack-tracing code can find the boundaries
+// of the interpreter.
+void *_Jv_StartOfInterpreter;
+void *_Jv_EndOfInterpreter;
+extern "C" void *_Unwind_FindEnclosingFunction (void *pc);
 
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
 {
   using namespace java::lang::reflect;
 
+  // Record the address of the start of this member function in
+  // _Jv_StartOfInterpreter.  Such a write to a global variable
+  // without acquiring a lock is correct iff reads and writes of words
+  // in memory are atomic, but Java requires that anyway.
+ foo:
+  if (_Jv_StartOfInterpreter == NULL)
+    _Jv_StartOfInterpreter = _Unwind_FindEnclosingFunction (&&foo);
+
   // FRAME_DESC registers this particular invocation as the top-most
   // interpreter frame.  This lets the stack tracing code (for
   // Throwable) print information about the method being interpreted
@@ -1032,9 +1054,14 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
 #define PCVAL(unionval) unionval.p
 #define AMPAMP(label) &&label
 
-  // Compile if we must.
+  // Compile if we must. NOTE: Double-check locking.
   if (prepared == NULL)
-    compile (insn_target);
+    {
+      _Jv_MutexLock (&compile_mutex);
+      if (prepared == NULL)
+       compile (insn_target);
+      _Jv_MutexUnlock (&compile_mutex);
+    }
   pc = (insn_slot *) prepared;
 
 #else
@@ -1156,7 +1183,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
        ffi_cif *cif = &rmeth->cif;
        ffi_raw *raw = (ffi_raw*) sp;
 
-       jdouble rvalue;
+       _Jv_value rvalue;
 
 #if FFI_NATIVE_RAW_API
        /* We assume that this is only implemented if it's correct      */
@@ -1172,11 +1199,11 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
         * so those are checked before the switch */
        if (rtype == FFI_TYPE_POINTER)
          {
-           PUSHA (*(jobject*)&rvalue);
+           PUSHA (rvalue.object_value);
          }
        else if (rtype == FFI_TYPE_SINT32)
          {
-           PUSHI (*(jint*)&rvalue);
+           PUSHI (rvalue.int_value);
          }
        else if (rtype == FFI_TYPE_VOID)
          {
@@ -1187,36 +1214,27 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
            switch (rtype)
              {
              case FFI_TYPE_SINT8:
-               {
-                 jbyte value = (*(jint*)&rvalue) & 0xff;
-                 PUSHI (value);
-               }
+               PUSHI ((jbyte)(rvalue.int_value & 0xff));
                break;
 
              case FFI_TYPE_SINT16:
-               {
-                 jshort value = (*(jint*)&rvalue) & 0xffff;
-                 PUSHI (value);
-               }
+               PUSHI ((jshort)(rvalue.int_value & 0xffff));
                break;
 
              case FFI_TYPE_UINT16:
-               {
-                 jint value = (*(jint*)&rvalue) & 0xffff;
-                 PUSHI (value);
-               }
+               PUSHI (rvalue.int_value & 0xffff);
                break;
 
              case FFI_TYPE_FLOAT:
-               PUSHF (*(jfloat*)&rvalue);
+               PUSHF (rvalue.float_value);
                break;
 
              case FFI_TYPE_DOUBLE:
-               PUSHD (rvalue);
+               PUSHD (rvalue.double_value);
                break;
 
              case FFI_TYPE_SINT64:
-               PUSHL (*(jlong*)&rvalue);
+               PUSHL (rvalue.long_value);
                break;
 
              default:
@@ -2408,37 +2426,37 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
            switch (type->size_in_bytes)
              {
              case 1:
-               PUSHI (*(jbyte*) (field->u.addr));
+               PUSHI (*field->u.byte_addr);
                newinsn = AMPAMP (getstatic_resolved_1);
                break;
 
              case 2:
                if (type == JvPrimClass (char))
                  {
-                   PUSHI(*(jchar*) (field->u.addr));
+                   PUSHI (*field->u.char_addr);
                    newinsn = AMPAMP (getstatic_resolved_char);
                  }
                else
                  {
-                   PUSHI(*(jshort*) (field->u.addr));
+                   PUSHI (*field->u.short_addr);
                    newinsn = AMPAMP (getstatic_resolved_short);
                  }
                break;
 
              case 4:
-               PUSHI(*(jint*) (field->u.addr));
+               PUSHI(*field->u.int_addr);
                newinsn = AMPAMP (getstatic_resolved_4);
                break;
 
              case 8:
-               PUSHL(*(jlong*) (field->u.addr));
+               PUSHL(*field->u.long_addr);
                newinsn = AMPAMP (getstatic_resolved_8);
                break;
              }
          }
        else
          {
-           PUSHA(*(jobject*) (field->u.addr));
+           PUSHA(*field->u.object_addr);
            newinsn = AMPAMP (getstatic_resolved_obj);
          }
 
@@ -2494,42 +2512,43 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
        NULLCHECK(obj);
 
        void *newinsn = NULL;
+       _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
        if (type->isPrimitive ())
          {
            switch (type->size_in_bytes)
              {
              case 1:
-               PUSHI (*(jbyte*) ((char*)obj + field_offset));
+               PUSHI (val->byte_value);
                newinsn = AMPAMP (getfield_resolved_1);
                break;
 
              case 2:
                if (type == JvPrimClass (char))
                  {
-                   PUSHI (*(jchar*) ((char*)obj + field_offset));
+                   PUSHI (val->char_value);
                    newinsn = AMPAMP (getfield_resolved_char);
                  }
                else
                  {
-                   PUSHI (*(jshort*) ((char*)obj + field_offset));
+                   PUSHI (val->short_value);
                    newinsn = AMPAMP (getfield_resolved_short);
                  }
                break;
 
              case 4:
-               PUSHI (*(jint*) ((char*)obj + field_offset));
+               PUSHI (val->int_value);
                newinsn = AMPAMP (getfield_resolved_4);
                break;
 
              case 8:
-               PUSHL(*(jlong*) ((char*)obj + field_offset));
+               PUSHL (val->long_value);
                newinsn = AMPAMP (getfield_resolved_8);
                break;
              }
          }
        else
          {
-           PUSHA(*(jobject*) ((char*)obj + field_offset));
+           PUSHA (val->object_value);
            newinsn = AMPAMP (getfield_resolved_obj);
          }
 
@@ -2611,7 +2630,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
              case 1:
                {
                  jint value = POPI();
-                 *(jbyte*) (field->u.addr) = value;
+                 *field->u.byte_addr = value;
                  newinsn = AMPAMP (putstatic_resolved_1);
                  break;
                }
@@ -2619,7 +2638,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
              case 2:
                {
                  jint value = POPI();
-                 *(jchar*) (field->u.addr) = value;
+                 *field->u.char_addr = value;
                  newinsn = AMPAMP (putstatic_resolved_2);
                  break;
                }
@@ -2627,7 +2646,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
              case 4:
                {
                  jint value = POPI();
-                 *(jint*) (field->u.addr) = value;
+                 *field->u.int_addr = value;
                  newinsn = AMPAMP (putstatic_resolved_4);
                  break;
                }
@@ -2635,7 +2654,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
              case 8:
                {
                  jlong value = POPL();
-                 *(jlong*) (field->u.addr) = value;
+                 *field->u.long_addr = value;
                  newinsn = AMPAMP (putstatic_resolved_8);
                  break;
                }
@@ -2644,7 +2663,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
        else
          {
            jobject value = POPA();
-           *(jobject*) (field->u.addr) = value;
+           *field->u.object_addr = value;
            newinsn = AMPAMP (putstatic_resolved_obj);
          }
 
@@ -2917,11 +2936,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
        int index = GET2U ();
        jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
-       // We initialize here because otherwise `size_in_bytes' may
-       // not be set correctly, leading us to pass `0' as the size.
-       // FIXME: fix in the allocator?  There is a PR for this.
-       _Jv_InitClass (klass);
-       jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
+       jobject res = _Jv_AllocObject (klass);
        PUSHA (res);
 
 #ifdef DIRECT_THREADED
@@ -2935,7 +2950,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     new_resolved:
       {
        jclass klass = (jclass) AVAL ();
-       jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
+       jobject res = _Jv_AllocObject (klass);
        PUSHA (res);
       }
       NEXT_INSN;
@@ -3133,6 +3148,10 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
            LOADI (wide);
            NEXT_INSN;
 
+         case op_fload:
+           LOADF (wide);
+           NEXT_INSN;
+
          case op_aload:
            LOADA (wide);
            NEXT_INSN;
@@ -3207,13 +3226,6 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     }
 }
 
-// This function exists so that the stack-tracing code can find the
-// boundaries of the interpreter.
-void
-_Jv_EndOfInterpreter (void)
-{
-}
-
 static void
 throw_internal_error (char *msg)
 {