OSDN Git Service

* libjava.jni/throwit.java: New file.
[pf3gnuchains/gcc-fork.git] / libjava / resolve.cc
index fc4c4df..634c08f 100644 (file)
@@ -1,6 +1,6 @@
 // resolve.cc - Code for linking and resolving classes and pool entries.
 
-/* Copyright (C) 1999  Red Hat, Inc.
+/* Copyright (C) 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -40,8 +40,6 @@ static void throw_class_format_error (jstring msg)
 static void throw_class_format_error (char *msg)
        __attribute__ ((__noreturn__));
 
-#define StringClass _CL_Q34java4lang6String
-extern java::lang::Class StringClass;
 #define ClassObject _CL_Q34java4lang6Object
 extern java::lang::Class ClassObject;
 #define ObjectClass _CL_Q34java4lang6Object
@@ -565,21 +563,21 @@ _Jv_PrepareClass(jclass klass)
      have code -- for static constructors. */
   for (int i = 0; i < clz->method_count; i++)
     {
-      _Jv_InterpMethod *imeth = clz->interpreted_methods[i];
+      _Jv_MethodBase *imeth = clz->interpreted_methods[i];
 
-      if (imeth != 0)          // it could be abstract or native
+      if ((clz->methods[i].accflags & Modifier::NATIVE) != 0)
        {
-         clz->methods[i].ncode = imeth->ncode ();
+         // You might think we could use a virtual `ncode' method in
+         // the _Jv_MethodBase and unify the native and non-native
+         // cases.  Well, we can't, because we don't allocate these
+         // objects using `new', and thus they don't get a vtable.
+         _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth);
+         clz->methods[i].ncode = jnim->ncode ();
        }
-      else
+      else if (imeth != 0)             // it could be abstract
        {
-         if ((clz->methods[i].accflags & Modifier::NATIVE) != 0)
-           {
-             JvThrow
-               (new java::lang::VirtualMachineError
-                (JvNewStringLatin1 
-                 ("the interpreter does not support native methods")));
-           }
+         _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
+         clz->methods[i].ncode = im->ncode ();
        }
     }
 
@@ -590,13 +588,6 @@ _Jv_PrepareClass(jclass klass)
       return;
     }
 
-  /* FIXME: native methods for interpreted classes should be handled, I
-   * dunno exactly how, but it seems that we should try to find them at
-   * this point, and if we fail, try again after <clinit>, since it
-   * could have caused additional code to be loaded.  Interfaces cannot
-   * have native methods (not even for static initialization). */
-
-
   /* Now onto the actual job: vtable layout.  First, count how many new
      methods we have */
   int new_method_count = 0;
@@ -659,10 +650,20 @@ _Jv_PrepareClass(jclass klass)
                           + (sizeof (void*) * (vtable_count)));
   vtable->clas = clz;
 
-  /* copy super class' vtable entries (index 0 goes unused). */
-  memcpy ((void*)&vtable->method[1],
-         (void*)&super_class->vtable->method[1],
-         sizeof (void*) * super_class->vtable_method_count);
+  {
+    jclass effective_superclass = super_class;
+
+    /* If super_class is abstract or an interface it has no vtable.
+       We need to find a real one... */
+    while (effective_superclass && effective_superclass->vtable == NULL)
+      effective_superclass = effective_superclass->superclass;
+
+    /* copy super class' vtable entries (index 0 goes unused). */
+    if (effective_superclass && effective_superclass->vtable)
+      memcpy ((void*)&vtable->method[1],
+             (void*)&effective_superclass->vtable->method[1],
+             sizeof (void*) * effective_superclass->vtable_method_count);
+  }
 
   /* now, install our own vtable entries, reprise... */
   for (int i = 0; i < clz->method_count; i++)
@@ -858,6 +859,16 @@ get_ffi_type_from_signature (unsigned char* ptr)
       break;
 
     case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+       return &ffi_type_sint8;
+      else
+       {
+         JvAssert (sizeof (jbyte) == sizeof (jint));
+         return &ffi_type_sint32;
+       }
+      break;
+
     case 'B':
       return &ffi_type_sint8;
       break;
@@ -930,7 +941,8 @@ init_cif (_Jv_Utf8Const* signature,
          int arg_count,
          jboolean staticp,
          ffi_cif *cif,
-         ffi_type **arg_types)
+         ffi_type **arg_types,
+         ffi_type **rtype_p)
 {
   unsigned char *ptr = (unsigned char*) signature->data;
 
@@ -972,6 +984,9 @@ init_cif (_Jv_Utf8Const* signature,
                    arg_count, rtype, arg_types) != FFI_OK)
     throw_internal_error ("ffi_prep_cif failed");
 
+  if (rtype_p != NULL)
+    *rtype_p = rtype;
+
   return item_count;
 }
 
@@ -1008,12 +1023,15 @@ _Jv_InterpMethod::ncode ()
            arg_count,
            staticp,
            &closure->cif,
-           &closure->arg_types[0]);
+           &closure->arg_types[0],
+           NULL);
 
   ffi_closure_fun fun;
 
   args_raw_size = ffi_raw_size (&closure->cif);
 
+  JvAssert ((self->accflags & Modifier::NATIVE) == 0);
+
   if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
     {
       if (staticp)
@@ -1027,15 +1045,77 @@ _Jv_InterpMethod::ncode ()
     }
 
   ffi_prep_raw_closure (&closure->closure,
-                    &closure->cif, 
-                    fun,
-                    (void*)this);
+                       &closure->cif, 
+                       fun,
+                       (void*) this);
 
   self->ncode = (void*)closure;
   return self->ncode;
 }
 
 
+void *
+_Jv_JNIMethod::ncode ()
+{
+  using namespace java::lang::reflect;
+
+  if (self->ncode != 0)
+    return self->ncode;
+
+  jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
+  int arg_count = count_arguments (self->signature, staticp);
+
+  ncode_closure *closure =
+    (ncode_closure*)_Jv_AllocBytesChecked (sizeof (ncode_closure)
+                                       + arg_count * sizeof (ffi_type*));
+
+  ffi_type *rtype;
+  init_cif (self->signature,
+           arg_count,
+           staticp,
+           &closure->cif,
+           &closure->arg_types[0],
+           &rtype);
+
+  ffi_closure_fun fun;
+
+  args_raw_size = ffi_raw_size (&closure->cif);
+
+  // Initialize the argument types and CIF that represent the actual
+  // underlying JNI function.
+  int extra_args = 1;
+  if ((self->accflags & Modifier::STATIC))
+    ++extra_args;
+  jni_arg_types = (ffi_type **) _Jv_Malloc ((extra_args + arg_count)
+                                           * sizeof (ffi_type *));
+  int offset = 0;
+  jni_arg_types[offset++] = &ffi_type_pointer;
+  if ((self->accflags & Modifier::STATIC))
+    jni_arg_types[offset++] = &ffi_type_pointer;
+  memcpy (&jni_arg_types[offset], &closure->arg_types[0],
+         arg_count * sizeof (ffi_type *));
+
+  if (ffi_prep_cif (&jni_cif, FFI_DEFAULT_ABI,
+                   extra_args + arg_count, rtype,
+                   jni_arg_types) != FFI_OK)
+    throw_internal_error ("ffi_prep_cif failed for JNI function");
+
+  JvAssert ((self->accflags & Modifier::NATIVE) != 0);
+
+  // FIXME: for now we assume that all native methods for
+  // interpreted code use JNI.
+  fun = (ffi_closure_fun) &_Jv_JNIMethod::call;
+
+  ffi_prep_raw_closure (&closure->closure,
+                       &closure->cif, 
+                       fun,
+                       (void*) this);
+
+  self->ncode = (void *) closure;
+  return self->ncode;
+}
+
+
 /* A _Jv_ResolvedMethod is what is put in the constant pool for a
  * MethodRef or InterfacemethodRef.  */
 static _Jv_ResolvedMethod*
@@ -1055,7 +1135,8 @@ _Jv_BuildResolvedMethod (_Jv_Method* method,
                arg_count,
                staticp,
                &result->cif,
-               &result->arg_types[0]);
+               &result->arg_types[0],
+               NULL);
 
   result->vtable_index        = vtable_index;
   result->method              = method;