OSDN Git Service

* java/nio/channels/Channels.java (newInputStream, newOutputStream):
[pf3gnuchains/gcc-fork.git] / libjava / resolve.cc
index df48c26..d71e125 100644 (file)
@@ -1,6 +1,6 @@
 // resolve.cc - Code for linking and resolving classes and pool entries.
 
-/* Copyright (C) 1999, 2000, 2001  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -11,6 +11,7 @@ details.  */
 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
 
 #include <config.h>
+#include <platform.h>
 
 #include <java-interp.h>
 
@@ -20,6 +21,7 @@ details.  */
 #include <java-cpool.h>
 #include <java/lang/Class.h>
 #include <java/lang/String.h>
+#include <java/lang/StringBuffer.h>
 #include <java/lang/Thread.h>
 #include <java/lang/InternalError.h>
 #include <java/lang/VirtualMachineError.h>
@@ -28,10 +30,13 @@ details.  */
 #include <java/lang/ClassFormatError.h>
 #include <java/lang/IllegalAccessError.h>
 #include <java/lang/AbstractMethodError.h>
-#include <java/lang/ClassNotFoundException.h>
+#include <java/lang/NoClassDefFoundError.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/VMClassLoader.h>
 #include <java/lang/reflect/Modifier.h>
 
+using namespace gcj;
+
 void
 _Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
 {
@@ -52,10 +57,6 @@ static void throw_class_format_error (jstring msg)
 static void throw_class_format_error (char *msg)
        __attribute__ ((__noreturn__));
 
-// Exceptional return values for _Jv_DetermineVTableIndex
-#define METHOD_NOT_THERE (-2)
-#define METHOD_INACCESSIBLE (-1)
-
 static int get_alignment_from_class (jclass);
 
 static _Jv_ResolvedMethod* 
@@ -65,9 +66,6 @@ _Jv_BuildResolvedMethod (_Jv_Method*,
                         jint);
 
 
-// We need to know the name of a constructor.
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
-
 static void throw_incompatible_class_change_error (jstring msg)
 {
   throw new java::lang::IncompatibleClassChangeError (msg);
@@ -98,7 +96,8 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
       if (! found)
        {
          jstring str = _Jv_NewStringUTF (name->data);
-         throw new java::lang::ClassNotFoundException (str);
+         // This exception is specified in JLS 2nd Ed, section 5.1.
+         throw new java::lang::NoClassDefFoundError (str);
        }
 
       if ((found->accflags & Modifier::PUBLIC) == Modifier::PUBLIC
@@ -168,15 +167,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
              if (! _Jv_equalUtf8Consts (field->name, field_name))
                continue;
 
-             // now, check field access. 
-
-             if (   (cls == klass)
-                 || ((field->flags & Modifier::PUBLIC) != 0)
-                 || (((field->flags & Modifier::PROTECTED) != 0)
-                     && cls->isAssignableFrom (klass))
-                 || (((field->flags & Modifier::PRIVATE) == 0)
-                     && _Jv_ClassNameSamePackage (cls->name,
-                                                  klass->name)))
+             if (_Jv_CheckAccess (klass, cls, field->flags))
                {
                  /* resove the field using the class' own loader
                     if necessary */
@@ -202,12 +193,13 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
     end_of_field_search:
       if (the_field == 0)
        {
-         jstring msg = JvNewStringLatin1 ("field ");
-         msg = msg->concat (owner->getName ());
-         msg = msg->concat (JvNewStringLatin1("."));
-         msg = msg->concat (_Jv_NewStringUTF (field_name->data));
-         msg = msg->concat (JvNewStringLatin1(" was not found."));
-         throw_incompatible_class_change_error (msg);
+         java::lang::StringBuffer *sb = new java::lang::StringBuffer();
+         sb->append(JvNewStringLatin1("field "));
+         sb->append(owner->getName());
+         sb->append(JvNewStringLatin1("."));
+         sb->append(_Jv_NewStringUTF(field_name->data));
+         sb->append(JvNewStringLatin1(" was not found."));
+         throw_incompatible_class_change_error(sb->toString());
        }
 
       pool->data[index].field = the_field;
@@ -235,13 +227,12 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
       _Jv_Utf8Const *method_name = pool->data[name_index].utf8;
       _Jv_Utf8Const *method_signature = pool->data[type_index].utf8;
 
-      int vtable_index = -1;
       _Jv_Method *the_method = 0;
       jclass found_class = 0;
 
       // First search the class itself.
       the_method = _Jv_SearchMethodInClass (owner, klass, 
-                  method_name, method_signature);
+                                           method_name, method_signature);
 
       if (the_method != 0)
         {
@@ -249,9 +240,10 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
           goto end_of_method_search;
        }
 
-      // If we are resolving an interface method, search the interface's 
-      // superinterfaces (A superinterface is not an interface's superclass - 
-      // a superinterface is implemented by the interface).
+      // If we are resolving an interface method, search the
+      // interface's superinterfaces (A superinterface is not an
+      // interface's superclass - a superinterface is implemented by
+      // the interface).
       if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
         {
          _Jv_ifaces ifaces;
@@ -260,8 +252,8 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
          ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
 
          _Jv_GetInterfaces (owner, &ifaces);     
-          
-         for (int i=0; i < ifaces.count; i++)
+
+         for (int i = 0; i < ifaces.count; i++)
            {
              jclass cls = ifaces.list[i];
              the_method = _Jv_SearchMethodInClass (cls, klass, method_name, 
@@ -272,9 +264,9 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
                   break;
                }
            }
-         
+
          _Jv_Free (ifaces.list);
-         
+
          if (the_method != 0)
            goto end_of_method_search;
        }
@@ -284,7 +276,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
            cls = cls->getSuperclass ())
        {
          the_method = _Jv_SearchMethodInClass (cls, klass, 
-                      method_name, method_signature);
+                                               method_name, method_signature);
           if (the_method != 0)
            {
              found_class = cls;
@@ -301,26 +293,21 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
       // with either loader should produce the same result,
       // i.e., exactly the same jclass object. JVMS 5.4.3.3    
     
-      if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
-       vtable_index = -1;
-      else
-       vtable_index = _Jv_DetermineVTableIndex
-         (found_class, method_name, method_signature);
-
-      if (vtable_index == METHOD_NOT_THERE)
-       throw_incompatible_class_change_error
-         (JvNewStringLatin1 ("method not found"));
-
       if (the_method == 0)
        {
-         jstring msg = JvNewStringLatin1 ("method ");
-         msg = msg->concat (owner->getName ());
-         msg = msg->concat (JvNewStringLatin1("."));
-         msg = msg->concat (_Jv_NewStringUTF (method_name->data));
-         msg = msg->concat (JvNewStringLatin1(" was not found."));
-         throw new java::lang::NoSuchMethodError (msg);
+         java::lang::StringBuffer *sb = new java::lang::StringBuffer();
+         sb->append(JvNewStringLatin1("method "));
+         sb->append(owner->getName());
+         sb->append(JvNewStringLatin1("."));
+         sb->append(_Jv_NewStringUTF(method_name->data));
+         sb->append(JvNewStringLatin1(" was not found."));
+         throw new java::lang::NoSuchMethodError (sb->toString());
        }
       
+      int vtable_index = -1;
+      if (pool->tags[index] != JV_CONSTANT_InterfaceMethodref)
+       vtable_index = (jshort)the_method->index;
+
       pool->data[index].rmethod = 
        _Jv_BuildResolvedMethod(the_method,
                                found_class,
@@ -353,139 +340,64 @@ _Jv_SearchMethodInClass (jclass cls, jclass klass,
                                    method_signature)))
        continue;
 
-      if (cls == klass 
-         || ((method->accflags & Modifier::PUBLIC) != 0)
-         || (((method->accflags & Modifier::PROTECTED) != 0)
-             && cls->isAssignableFrom (klass))
-         || (((method->accflags & Modifier::PRIVATE) == 0)
-             && _Jv_ClassNameSamePackage (cls->name,
-                                          klass->name)))
-       {
-         return method;
-       }
+      if (_Jv_CheckAccess (klass, cls, method->accflags))
+       return method;
       else
-       {
-         throw new java::lang::IllegalAccessError;
-       }
+       throw new java::lang::IllegalAccessError;
     }
   return 0;
 }
 
-/** FIXME: this is a terribly inefficient algorithm!  It would improve
-    things if compiled classes to know vtable offset, and _Jv_Method had
-    a field for this.
-
-    Returns METHOD_NOT_THERE if this class does not declare the given method.
-    Returns METHOD_INACCESSIBLE if the given method does not appear in the
-               vtable, i.e., it is static, private, final or a constructor.
-    Otherwise, returns the vtable index.  */
-int 
-_Jv_DetermineVTableIndex (jclass klass,
-                         _Jv_Utf8Const *name,
-                         _Jv_Utf8Const *signature)
+// A helper for _Jv_PrepareClass.  This adds missing `Miranda methods'
+// to a class.
+void
+_Jv_PrepareMissingMethods (jclass base2, jclass iface_class)
 {
-  using namespace java::lang::reflect;
-
-  jclass super_class = klass->getSuperclass ();
-
-  if (super_class != NULL)
+  _Jv_InterpClass *base = reinterpret_cast<_Jv_InterpClass *> (base2);
+  for (int i = 0; i < iface_class->interface_count; ++i)
     {
-      int prev = _Jv_DetermineVTableIndex (super_class,
-                                          name,
-                                          signature);
-      if (prev != METHOD_NOT_THERE)
-       return prev;
-    }
-
-  /* at this point, we know that the super-class does not declare
-   * the method.  Otherwise, the above call would have found it, and
-   * determined the result of this function (-1 or some positive
-   * number).
-   */
-
-  _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
-
-  /* now, if we do not declare this method, return zero */
-  if (meth == NULL)
-    return METHOD_NOT_THERE;
-
-  /* so now, we know not only that the super class does not declare the
-   * method, but we do!  So, this is a first declaration of the method. */
-
-  /* now, the checks for things that are declared in this class, but do
-   * not go into the vtable.  There are three cases.  
-   * 1) the method is static, private or final
-   * 2) the class itself is final, or
-   * 3) it is the method <init>
-   */
-
-  if ((meth->accflags & (Modifier::STATIC
-                        | Modifier::PRIVATE
-                        | Modifier::FINAL)) != 0
-      || (klass->accflags & Modifier::FINAL) != 0
-      || _Jv_equalUtf8Consts (name, init_name))
-    return METHOD_INACCESSIBLE;
-
-  /* reaching this point, we know for sure, that the method in question
-   * will be in the vtable.  The question is where. */
-
-  /* the base offset, is where we will start assigning vtable
-   * indexes for this class.  It is 0 for base classes
-   * and for non-base classes it is the
-   * number of entries in the super class' vtable. */
-
-  int base_offset;
-  if (super_class == 0)
-    base_offset = 0;
-  else
-    base_offset = super_class->vtable_method_count;
-
-  /* we will consider methods 0..this_method_index-1.  And for each one,
-   * determine if it is new (i.e., if it appears in the super class),
-   * and if it should go in the vtable.  If so, increment base_offset */
-
-  int this_method_index = meth - (&klass->methods[0]);
-
-  for (int i = 0; i < this_method_index; i++)
-    {
-      _Jv_Method *m = &klass->methods[i];
-
-      /* fist some checks for things that surely do not go in the
-       * vtable */
-
-      if ((m->accflags & (Modifier::STATIC | Modifier::PRIVATE)) != 0)
-       continue;
-      if (_Jv_equalUtf8Consts (m->name, init_name))
-       continue;
-      
-      /* Then, we need to know if this method appears in the
-         superclass. (This is where this function gets expensive) */
-      _Jv_Method *sm = _Jv_LookupDeclaredMethod (super_class,
-                                                m->name,
-                                                m->signature);
-      
-      /* if it was somehow declared in the superclass, skip this */
-      if (sm != NULL)
-       continue;
-
-      /* but if it is final, and not declared in the super class,
-       * then we also skip it */
-      if ((m->accflags & Modifier::FINAL) != 0)
-       continue;
+      for (int j = 0; j < iface_class->interfaces[i]->method_count; ++j)
+       {
+         _Jv_Method *meth = &iface_class->interfaces[i]->methods[j];
+         // Don't bother with <clinit>.
+         if (meth->name->data[0] == '<')
+           continue;
+         _Jv_Method *new_meth = _Jv_LookupDeclaredMethod (base, meth->name,
+                                                          meth->signature);
+         if (! new_meth)
+           {
+             // We assume that such methods are very unlikely, so we
+             // just reallocate the method array each time one is
+             // found.  This greatly simplifies the searching --
+             // otherwise we have to make sure that each such method
+             // found is really unique among all superinterfaces.
+             int new_count = base->method_count + 1;
+             _Jv_Method *new_m
+               = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method)
+                                                * new_count);
+             memcpy (new_m, base->methods,
+                     sizeof (_Jv_Method) * base->method_count);
+
+             // Add new method.
+             new_m[base->method_count] = *meth;
+             new_m[base->method_count].index = (_Jv_ushort) -1;
+             new_m[base->method_count].accflags
+               |= java::lang::reflect::Modifier::INVISIBLE;
+
+             _Jv_MethodBase **new_im
+               = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *)
+                                                     * new_count);
+             memcpy (new_im, base->interpreted_methods,
+                     sizeof (_Jv_MethodBase *) * base->method_count);
+
+             base->methods = new_m;
+             base->interpreted_methods = new_im;
+             base->method_count = new_count;
+           }
+       }
 
-      /* finally, we can assign the index of this method */
-      /* m->vtable_index = base_offset */
-      base_offset += 1;
+      _Jv_PrepareMissingMethods (base, iface_class->interfaces[i]);
     }
-
-  return base_offset;
-}
-
-/* this is installed in place of abstract methods */
-static void
-_Jv_abstractMethodError ()
-{
-  throw new java::lang::AbstractMethodError;
 }
 
 void 
@@ -517,22 +429,49 @@ _Jv_PrepareClass(jclass klass)
   if (klass->state >= JV_STATE_PREPARED)
     return;
 
-  // make sure super-class is linked.  This involves taking a lock on
-  // the super class, so we use the Java method resolveClass, which will
-  // unlock it properly, should an exception happen.
+  // Make sure super-class is linked.  This involves taking a lock on
+  // the super class, so we use the Java method resolveClass, which
+  // will unlock it properly, should an exception happen.  If there's
+  // no superclass, do nothing -- Object will already have been
+  // resolved.
 
-  java::lang::ClassLoader::resolveClass0 (klass->superclass);
+  if (klass->superclass)
+    java::lang::VMClassLoader::resolveClass (klass->superclass);
 
   _Jv_InterpClass *clz = (_Jv_InterpClass*)klass;
 
   /************ PART ONE: OBJECT LAYOUT ***************/
 
+  // Compute the alignment for this type by searching through the
+  // superclasses and finding the maximum required alignment.  We
+  // could consider caching this in the Class.
+  int max_align = __alignof__ (java::lang::Object);
+  jclass super = clz->superclass;
+  while (super != NULL)
+    {
+      int num = JvNumInstanceFields (super);
+      _Jv_Field *field = JvGetFirstInstanceField (super);
+      while (num > 0)
+       {
+         int field_align = get_alignment_from_class (field->type);
+         if (field_align > max_align)
+           max_align = field_align;
+         ++field;
+         --num;
+       }
+      super = super->superclass;
+    }
+
   int instance_size;
-  int static_size;
+  int static_size = 0;
 
-  // java.lang.Object is never interpreted!
-  instance_size = clz->superclass->size ();
-  static_size   = 0;
+  // Although java.lang.Object is never interpreted, an interface can
+  // have a null superclass.  Note that we have to lay out an
+  // interface because it might have static fields.
+  if (clz->superclass)
+    instance_size = clz->superclass->size();
+  else
+    instance_size = java::lang::Object::class$.size();
 
   for (int i = 0; i < clz->field_count; i++)
     {
@@ -574,12 +513,17 @@ _Jv_PrepareClass(jclass klass)
          instance_size      = ROUND (instance_size, field_align);
          field->u.boffset   = instance_size;
          instance_size     += field_size;
+         if (field_align > max_align)
+           max_align = field_align;
        }
     }
 
-  // set the instance size for the class
+  // Set the instance size for the class.  Note that first we round it
+  // to the alignment required for this object; this keeps us in sync
+  // with our current ABI.
+  instance_size = ROUND (instance_size, max_align);
   clz->size_in_bytes = instance_size;
-    
+
   // allocate static memory
   if (static_size != 0)
     {
@@ -629,117 +573,41 @@ _Jv_PrepareClass(jclass klass)
       else if (imeth != 0)             // it could be abstract
        {
          _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
+         _Jv_VerifyMethod (im);
          clz->methods[i].ncode = im->ncode ();
+
+         // Resolve ctable entries pointing to this method.  See
+         // _Jv_Defer_Resolution.
+         void **code = (void **)imeth->deferred;
+         while (code)
+           {
+             void **target = (void **)*code;
+             *code = clz->methods[i].ncode;
+             code = target;
+           }
        }
     }
 
-  if (clz->accflags & Modifier::INTERFACE)
+  if ((clz->accflags & Modifier::INTERFACE))
     {
       clz->state = JV_STATE_PREPARED;
       clz->notifyAll ();
       return;
     }
 
-  /* Now onto the actual job: vtable layout.  First, count how many new
-     methods we have */
-  int new_method_count = 0;
-
-  jclass super_class = clz->getSuperclass ();
+  // A class might have so-called "Miranda methods".  This is a method
+  // that is declared in an interface and not re-declared in an
+  // abstract class.  Some compilers don't emit declarations for such
+  // methods in the class; this will give us problems since we expect
+  // a declaration for any method requiring a vtable entry.  We handle
+  // this here by searching for such methods and constructing new
+  // internal declarations for them.  We only need to do this for
+  // abstract classes.
+  if ((clz->accflags & Modifier::ABSTRACT))
+    _Jv_PrepareMissingMethods (clz, clz);
 
-  if (super_class == 0)
-    throw_internal_error ("cannot handle interpreted base classes");
-
-  for (int i = 0; i < clz->method_count; i++)
-    {
-      _Jv_Method *this_meth = &clz->methods[i];
-
-      if ((this_meth->accflags & (Modifier::STATIC | Modifier::PRIVATE)) != 0
-         || _Jv_equalUtf8Consts (this_meth->name, init_name))
-       {
-         /* skip this, it doesn't go in the vtable */
-         continue;
-       }
-         
-      _Jv_Method *orig_meth = _Jv_LookupDeclaredMethod (super_class,
-                                                       this_meth->name,
-                                                       this_meth->signature);
-
-      if (orig_meth == 0)
-       {
-         // new methods that are final, also don't go in the vtable
-         if ((this_meth->accflags & Modifier::FINAL) != 0)
-           continue;
-
-         new_method_count += 1;
-         continue;
-       }
-
-      if ((orig_meth->accflags & (Modifier::STATIC
-                                 | Modifier::PRIVATE
-                                 | Modifier::FINAL)) != 0
-         || ((orig_meth->accflags & Modifier::ABSTRACT) == 0
-             && (this_meth->accflags & Modifier::ABSTRACT) != 0
-             && (klass->accflags & Modifier::ABSTRACT) == 0))
-       {
-         clz->state = JV_STATE_ERROR;
-         clz->notifyAll ();
-         throw new java::lang::IncompatibleClassChangeError (clz->getName ());
-       }
-
-      /* FIXME: At this point, if (loader != super_class->loader), we
-       * need to "impose class loader constraints" for the types
-       * involved in the signature of this method */
-    }
-  
-  /* determine size */
-  int vtable_count = (super_class->vtable_method_count) + new_method_count;
-  clz->vtable_method_count = vtable_count;
-
-  /* allocate vtable structure */
-  _Jv_VTable *vtable = _Jv_VTable::new_vtable (vtable_count);
-  vtable->clas = clz;
-  vtable->gc_descr = _Jv_BuildGCDescr(clz);
-
-  {
-    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. */
-    if (effective_superclass && effective_superclass->vtable)
-      for (int i = 0; i < effective_superclass->vtable_method_count; ++i)
-       vtable->set_method (i, effective_superclass->vtable->get_method (i));
-  }
-
-  /* now, install our own vtable entries, reprise... */
-  for (int i = 0; i < clz->method_count; i++)
-    {
-      _Jv_Method *this_meth = &clz->methods[i];
-
-      int index = _Jv_DetermineVTableIndex (clz, 
-                                           this_meth->name,
-                                           this_meth->signature);
-
-      if (index == METHOD_NOT_THERE)
-       throw_internal_error ("method now found in own class");
-
-      if (index != METHOD_INACCESSIBLE)
-       {
-         if (index > clz->vtable_method_count)
-           throw_internal_error ("vtable problem...");
-
-         if (clz->interpreted_methods[i] == 0)
-           vtable->set_method(index, (void*)&_Jv_abstractMethodError);
-         else
-           vtable->set_method(index, this_meth->ncode);
-       }
-    }
-
-  /* finally, assign the vtable! */
-  clz->vtable = vtable;
+  clz->vtable_method_count = -1;
+  _Jv_MakeVTable (clz);
 
   /* wooha! we're done. */
   clz->state = JV_STATE_PREPARED;
@@ -856,27 +724,39 @@ _Jv_InitField (jobject obj, jclass klass, int index)
     }
 }
 
+template<typename T>
+struct aligner
+{
+  T field;
+};
+
+#define ALIGNOF(TYPE) (__alignof__ (((aligner<TYPE> *) 0)->field))
+
+// This returns the alignment of a type as it would appear in a
+// structure.  This can be different from the alignment of the type
+// itself.  For instance on x86 double is 8-aligned but struct{double}
+// is 4-aligned.
 static int
 get_alignment_from_class (jclass klass)
 {
   if (klass == JvPrimClass (byte))
-    return  __alignof__ (jbyte);
+    return ALIGNOF (jbyte);
   else if (klass == JvPrimClass (short))
-    return  __alignof__ (jshort);
+    return ALIGNOF (jshort);
   else if (klass == JvPrimClass (int)) 
-    return  __alignof__ (jint);
+    return ALIGNOF (jint);
   else if (klass == JvPrimClass (long))
-    return  __alignof__ (jlong);
+    return ALIGNOF (jlong);
   else if (klass == JvPrimClass (boolean))
-    return  __alignof__ (jboolean);
+    return ALIGNOF (jboolean);
   else if (klass == JvPrimClass (char))
-    return  __alignof__ (jchar);
+    return ALIGNOF (jchar);
   else if (klass == JvPrimClass (float))
-    return  __alignof__ (jfloat);
+    return ALIGNOF (jfloat);
   else if (klass == JvPrimClass (double))
-    return  __alignof__ (jdouble);
+    return ALIGNOF (jdouble);
   else
-    return __alignof__ (jobject);
+    return ALIGNOF (jobject);
 }
 
 
@@ -959,9 +839,9 @@ get_ffi_type_from_signature (unsigned char* ptr)
  * function is non-static, then one is added to the number of elements
  * found in the signature */
 
-static int 
-count_arguments (_Jv_Utf8Const *signature,
-                jboolean staticp)
+int 
+_Jv_count_arguments (_Jv_Utf8Const *signature,
+                    jboolean staticp)
 {
   unsigned char *ptr = (unsigned char*) signature->data;
   int arg_count = staticp ? 0 : 1;
@@ -1049,7 +929,7 @@ init_cif (_Jv_Utf8Const* signature,
 #endif
 
 /* we put this one here, and not in interpret.cc because it
- * calls the utility routines count_arguments 
+ * calls the utility routines _Jv_count_arguments 
  * which are static to this module.  The following struct defines the
  * layout we use for the stubs, it's only used in the ncode method. */
 
@@ -1070,7 +950,7 @@ _Jv_InterpMethod::ncode ()
     return self->ncode;
 
   jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
-  int arg_count = count_arguments (self->signature, staticp);
+  int arg_count = _Jv_count_arguments (self->signature, staticp);
 
   ncode_closure *closure =
     (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
@@ -1098,7 +978,10 @@ _Jv_InterpMethod::ncode ()
     }
   else
     {
-      fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+      if (staticp)
+       fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+      else
+       fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
     }
 
   FFI_PREP_RAW_CLOSURE (&closure->closure,
@@ -1110,7 +993,6 @@ _Jv_InterpMethod::ncode ()
   return self->ncode;
 }
 
-
 void *
 _Jv_JNIMethod::ncode ()
 {
@@ -1120,7 +1002,7 @@ _Jv_JNIMethod::ncode ()
     return self->ncode;
 
   jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
-  int arg_count = count_arguments (self->signature, staticp);
+  int arg_count = _Jv_count_arguments (self->signature, staticp);
 
   ncode_closure *closure =
     (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
@@ -1152,7 +1034,7 @@ _Jv_JNIMethod::ncode ()
   memcpy (&jni_arg_types[offset], &closure->arg_types[0],
          arg_count * sizeof (ffi_type *));
 
-  if (ffi_prep_cif (&jni_cif, FFI_DEFAULT_ABI,
+  if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi,
                    extra_args + arg_count, rtype,
                    jni_arg_types) != FFI_OK)
     throw_internal_error ("ffi_prep_cif failed for JNI function");
@@ -1181,7 +1063,7 @@ _Jv_BuildResolvedMethod (_Jv_Method* method,
                         jboolean staticp,
                         jint vtable_index)
 {
-  int arg_count = count_arguments (method->signature, staticp);
+  int arg_count = _Jv_count_arguments (method->signature, staticp);
 
   _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*)
     _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod)