OSDN Git Service

* java/lang/natDouble.cc (parseDouble): Cannot use errno to
[pf3gnuchains/gcc-fork.git] / libjava / resolve.cc
index a2d61c9..b0a0565 100644 (file)
@@ -1,6 +1,6 @@
 // resolve.cc - Code for linking and resolving classes and pool entries.
 
-/* Copyright (C) 1999  Cygnus Solutions
+/* Copyright (C) 1999, 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -10,12 +10,12 @@ details.  */
 
 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
 
-#include <java-interp.h>
+#include <config.h>
 
-#ifdef INTERPRETER
+#include <java-interp.h>
 
-#include <cni.h>
 #include <jvm.h>
+#include <gcj/cni.h>
 #include <string.h>
 #include <java-cpool.h>
 #include <java/lang/Class.h>
@@ -24,11 +24,26 @@ details.  */
 #include <java/lang/InternalError.h>
 #include <java/lang/VirtualMachineError.h>
 #include <java/lang/NoSuchFieldError.h>
+#include <java/lang/NoSuchMethodError.h>
 #include <java/lang/ClassFormatError.h>
 #include <java/lang/IllegalAccessError.h>
 #include <java/lang/AbstractMethodError.h>
 #include <java/lang/ClassNotFoundException.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/reflect/Modifier.h>
+
+void
+_Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
+{
+  if (! field->isResolved ())
+    {
+      _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type;
+      field->type = _Jv_FindClassFromSignature (sig->data, loader);
+      field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
+    }
+}
+
+#ifdef INTERPRETER
 
 static void throw_internal_error (char *msg)
        __attribute__ ((__noreturn__));
@@ -37,13 +52,9 @@ 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
-extern java::lang::Class ObjectClass;
-
+// Exceptional return values for _Jv_DetermineVTableIndex
+#define METHOD_NOT_THERE (-2)
+#define METHOD_INACCESSIBLE (-1)
 
 static int get_alignment_from_class (jclass);
 
@@ -54,19 +65,6 @@ _Jv_BuildResolvedMethod (_Jv_Method*,
                         jint);
 
 
-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; 
-
 // We need to know the name of a constructor.
 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
 
@@ -75,9 +73,11 @@ static void throw_incompatible_class_change_error (jstring msg)
   JvThrow (new java::lang::IncompatibleClassChangeError (msg));
 }
 
-void*
+_Jv_word
 _Jv_ResolvePoolEntry (jclass klass, int index)
 {
+  using namespace java::lang::reflect;
+
   _Jv_Constants *pool = &klass->constants;
 
   if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
@@ -86,7 +86,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
   switch (pool->tags[index]) {
   case JV_CONSTANT_Class:
     {
-      _Jv_Utf8Const *name = (_Jv_Utf8Const *) pool->data[index];
+      _Jv_Utf8Const *name = pool->data[index].utf8;
 
       jclass found;
       if (name->data[0] == '[')
@@ -101,11 +101,11 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
          JvThrow (new java::lang::ClassNotFoundException (str));
        }
 
-      if ((found->accflags & PUBLIC) == PUBLIC
+      if ((found->accflags & Modifier::PUBLIC) == Modifier::PUBLIC
          || (_Jv_ClassNameSamePackage (found->name,
                                        klass->name)))
        {
-         pool->data[index] = (void *) found;
+         pool->data[index].clazz = found;
          pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
        }
       else
@@ -118,31 +118,31 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
   case JV_CONSTANT_String:
     {
       jstring str;
-      str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) pool->data[index]);
-      pool->data[index] = (void *) str;
+      str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
+      pool->data[index].o = str;
       pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
     }
     break;
 
+
   case JV_CONSTANT_Fieldref:
     {
       _Jv_ushort class_index, name_and_type_index;
-      _Jv_loadIndexes ((const void**) &pool->data[index],
+      _Jv_loadIndexes (&pool->data[index],
                       class_index,
                       name_and_type_index);
-      jclass owner = (jclass) _Jv_ResolvePoolEntry (klass, class_index);
+      jclass owner = (_Jv_ResolvePoolEntry (klass, class_index)).clazz;
 
       if (owner != klass)
        _Jv_InitClass (owner);
 
       _Jv_ushort name_index, type_index;
-      _Jv_loadIndexes ((const void**) &pool->data[name_and_type_index],
+      _Jv_loadIndexes (&pool->data[name_and_type_index],
                       name_index,
                       type_index);
 
-      _Jv_Utf8Const *field_name = (_Jv_Utf8Const*) pool->data[name_index];
-      _Jv_Utf8Const *field_type_name =
-       (_Jv_Utf8Const*) pool->data[type_index];
+      _Jv_Utf8Const *field_name = pool->data[name_index].utf8;
+      _Jv_Utf8Const *field_type_name = pool->data[type_index].utf8;
 
       // FIXME: The implementation of this function
       // (_Jv_FindClassFromSignature) will generate an instance of
@@ -171,10 +171,10 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
              // now, check field access. 
 
              if (   (cls == klass)
-                 || ((field->flags & PUBLIC) != 0)
-                 || (((field->flags & PROTECTED) != 0)
+                 || ((field->flags & Modifier::PUBLIC) != 0)
+                 || (((field->flags & Modifier::PROTECTED) != 0)
                      && cls->isAssignableFrom (klass))
-                 || (((field->flags & PRIVATE) == 0)
+                 || (((field->flags & Modifier::PRIVATE) == 0)
                      && _Jv_ClassNameSamePackage (cls->name,
                                                   klass->name)))
                {
@@ -211,7 +211,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
          throw_incompatible_class_change_error (msg);
        }
 
-      pool->data[index] = (void*)the_field;
+      pool->data[index].field = the_field;
       pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
     }
     break;
@@ -220,80 +220,98 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
   case JV_CONSTANT_InterfaceMethodref:
     {
       _Jv_ushort class_index, name_and_type_index;
-      _Jv_loadIndexes ((const void**) &pool->data[index],
+      _Jv_loadIndexes (&pool->data[index],
                       class_index,
                       name_and_type_index);
-      jclass owner = (jclass) _Jv_ResolvePoolEntry (klass, class_index);
+      jclass owner = (_Jv_ResolvePoolEntry (klass, class_index)).clazz;
 
       if (owner != klass)
        _Jv_InitClass (owner);
 
       _Jv_ushort name_index, type_index;
-      _Jv_loadIndexes ((const void**) &pool->data[name_and_type_index],
+      _Jv_loadIndexes (&pool->data[name_and_type_index],
                       name_index,
                       type_index);
 
-      _Jv_Utf8Const *method_name = (_Jv_Utf8Const*) pool->data[name_index];
-      _Jv_Utf8Const *method_signature =
-       (_Jv_Utf8Const*) pool->data[type_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;
 
-      // we make a loop here, because methods are allowed to be moved to
-      // a super class, and still be visible.. (binary compatibility).
+      // First search the class itself.
+      the_method = _Jv_SearchMethodInClass (owner, klass, 
+                  method_name, method_signature);
 
-      for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
-       {
-         for (int i = 0;  i < cls->method_count;  i++)
-           {
-             _Jv_Method *method = &cls->methods[i];
-             if (   (!_Jv_equalUtf8Consts (method->name,
-                                           method_name))
-                 || (!_Jv_equalUtf8Consts (method->signature,
-                                           method_signature)))
-               continue;
+      if (the_method != 0)
+        {
+         found_class = owner;
+          goto end_of_method_search;
+       }
 
-             if (cls == klass 
-                 || ((method->accflags & PUBLIC) != 0)
-                 || (((method->accflags & PROTECTED) != 0)
-                     && cls->isAssignableFrom (klass))
-                 || (((method->accflags & PRIVATE) == 0)
-                     && _Jv_ClassNameSamePackage (cls->name,
-                                                  klass->name)))
-               {
-                 // FIXME: if (cls->loader != klass->loader), then we
-                 // must actually check that the types of arguments
-                 // correspond.  That is, for each argument type, and
-                 // the return type, doing _Jv_FindClassFromSignature
-                 // with either loader should produce the same result,
-                 // i.e., exactly the same jclass object. JVMS 5.4.3.3
-
-                 the_method = method;
+      // 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;
+         ifaces.count = 0;
+         ifaces.len = 4;
+         ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
+
+         _Jv_GetInterfaces (owner, &ifaces);     
+          
+         for (int i=0; i < ifaces.count; i++)
+           {
+             jclass cls = ifaces.list[i];
+             the_method = _Jv_SearchMethodInClass (cls, klass, method_name, 
+                                                   method_signature);
+             if (the_method != 0)
+               {
                  found_class = cls;
-
-                 
-                 if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
-                   vtable_index = -1;
-                 else
-                   vtable_index = _Jv_DetermineVTableIndex
-                     (cls, method_name, method_signature);
-
-                 if (vtable_index == 0)
-                   throw_incompatible_class_change_error
-                     (JvNewStringLatin1 ("method not found"));
-
-                 goto end_of_method_search;
-               }
-             else
-               {
-                 JvThrow (new java::lang::IllegalAccessError);
+                  break;
                }
            }
+         
+         _Jv_Free (ifaces.list);
+         
+         if (the_method != 0)
+           goto end_of_method_search;
+       }
+
+      // Finally, search superclasses. 
+      for (jclass cls = owner->getSuperclass (); cls != 0; 
+           cls = cls->getSuperclass ())
+       {
+         the_method = _Jv_SearchMethodInClass (cls, klass, 
+                      method_name, method_signature);
+          if (the_method != 0)
+           {
+             found_class = cls;
+             break;
+           }
        }
 
     end_of_method_search:
+    
+      // FIXME: if (cls->loader != klass->loader), then we
+      // must actually check that the types of arguments
+      // correspond.  That is, for each argument type, and
+      // the return type, doing _Jv_FindClassFromSignature
+      // 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 ");
@@ -301,13 +319,13 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
          msg = msg->concat (JvNewStringLatin1("."));
          msg = msg->concat (_Jv_NewStringUTF (method_name->data));
          msg = msg->concat (JvNewStringLatin1(" was not found."));
-         JvThrow(new java::lang::NoSuchFieldError (msg));
+         JvThrow(new java::lang::NoSuchMethodError (msg));
        }
       
-      pool->data[index] = (void*)
+      pool->data[index].rmethod = 
        _Jv_BuildResolvedMethod(the_method,
                                found_class,
-                               ((the_method->accflags & STATIC) != 0),
+                               (the_method->accflags & Modifier::STATIC) != 0,
                                vtable_index);
       pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
     }
@@ -318,45 +336,57 @@ _Jv_ResolvePoolEntry (jclass klass, int index)
   return pool->data[index];
 }
 
-void
-_Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
+// Find a method declared in the cls that is referenced from klass and
+// perform access checks.
+_Jv_Method *
+_Jv_SearchMethodInClass (jclass cls, jclass klass, 
+                         _Jv_Utf8Const *method_name, 
+                        _Jv_Utf8Const *method_signature)
 {
-  if (! field->isResolved ())
-    {
-      _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type;
-      field->type = _Jv_FindClassFromSignature (sig->data, loader);
-      field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
-    }
-}
+  using namespace java::lang::reflect;
 
-_Jv_Method*
-_Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
-                       _Jv_Utf8Const *signature)
-{
-  for (; klass; klass = klass->getSuperclass())
+  for (int i = 0;  i < cls->method_count;  i++)
     {
-      _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
+      _Jv_Method *method = &cls->methods[i];
+      if (   (!_Jv_equalUtf8Consts (method->name,
+                                   method_name))
+         || (!_Jv_equalUtf8Consts (method->signature,
+                                   method_signature)))
+       continue;
 
-      if (meth)
-       return meth;
+      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;
+       }
+      else
+       {
+         JvThrow (new java::lang::IllegalAccessError);
+       }
     }
-
-  return NULL;
+  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  if this class does not declare the given method.
-    Returns -1 if the given method does not appear in the vtable.
-               i.e., it is static, private, final or a constructor.
+    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)
 {
+  using namespace java::lang::reflect;
+
   jclass super_class = klass->getSuperclass ();
 
   if (super_class != NULL)
@@ -364,7 +394,7 @@ _Jv_DetermineVTableIndex (jclass klass,
       int prev = _Jv_DetermineVTableIndex (super_class,
                                           name,
                                           signature);
-      if (prev != 0)
+      if (prev != METHOD_NOT_THERE)
        return prev;
     }
 
@@ -378,7 +408,7 @@ _Jv_DetermineVTableIndex (jclass klass,
 
   /* now, if we do not declare this method, return zero */
   if (meth == NULL)
-    return 0;
+    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. */
@@ -390,24 +420,26 @@ _Jv_DetermineVTableIndex (jclass klass,
    * 3) it is the method <init>
    */
 
-  if (   (meth->accflags & (STATIC|PRIVATE|FINAL)) != 0
-      || (klass->accflags & FINAL) != 0
+  if ((meth->accflags & (Modifier::STATIC
+                        | Modifier::PRIVATE
+                        | Modifier::FINAL)) != 0
+      || (klass->accflags & Modifier::FINAL) != 0
       || _Jv_equalUtf8Consts (name, init_name))
-    return -1;
+    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 1 for base classes
-   * (vtable->method[0] is unused), and for non-base classes it is the
-   * number of entries in the super class' vtable plus 1. */
+   * 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 = 1;
+    base_offset = 0;
   else
-    base_offset = super_class->vtable_method_count+1;
+    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),
@@ -422,7 +454,7 @@ _Jv_DetermineVTableIndex (jclass klass,
       /* fist some checks for things that surely do not go in the
        * vtable */
 
-      if ((m->accflags & (STATIC|PRIVATE)) != 0)
+      if ((m->accflags & (Modifier::STATIC | Modifier::PRIVATE)) != 0)
        continue;
       if (_Jv_equalUtf8Consts (m->name, init_name))
        continue;
@@ -439,7 +471,7 @@ _Jv_DetermineVTableIndex (jclass klass,
 
       /* but if it is final, and not declared in the super class,
        * then we also skip it */
-      if ((m->accflags & FINAL) != 0)
+      if ((m->accflags & Modifier::FINAL) != 0)
        continue;
 
       /* finally, we can assign the index of this method */
@@ -460,6 +492,8 @@ _Jv_abstractMethodError ()
 void 
 _Jv_PrepareClass(jclass klass)
 {
+  using namespace java::lang::reflect;
+
  /*
   * The job of this function is to: 1) assign storage to fields, and 2)
   * build the vtable.  static fields are assigned real memory, instance
@@ -488,7 +522,7 @@ _Jv_PrepareClass(jclass klass)
   // the super class, so we use the Java method resolveClass, which will
   // unlock it properly, should an exception happen.
 
-  java::lang::ClassLoader::resolveClass (klass->superclass);
+  java::lang::ClassLoader::resolveClass0 (klass->superclass);
 
   _Jv_InterpClass *clz = (_Jv_InterpClass*)klass;
 
@@ -527,7 +561,7 @@ _Jv_PrepareClass(jclass klass)
       field->bsize = field_size;
 #endif
 
-      if (field->flags & STATIC)
+      if (field->flags & Modifier::STATIC)
        {
          /* this computes an offset into a region we'll allocate 
             shortly, and then add this offset to the start address */
@@ -558,7 +592,7 @@ _Jv_PrepareClass(jclass klass)
        {
          _Jv_Field *field = &clz->fields[i];
 
-         if ((field->flags & STATIC) != 0)
+         if ((field->flags & Modifier::STATIC) != 0)
            {
              field->u.addr  = static_data + field->u.boffset;
                            
@@ -582,38 +616,31 @@ _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 & 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 ();
        }
     }
 
-  if (clz->accflags & INTERFACE)
+  if (clz->accflags & Modifier::INTERFACE)
     {
       clz->state = JV_STATE_PREPARED;
       clz->notifyAll ();
       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;
@@ -627,7 +654,7 @@ _Jv_PrepareClass(jclass klass)
     {
       _Jv_Method *this_meth = &clz->methods[i];
 
-      if ((this_meth->accflags & (STATIC|PRIVATE)) != 0
+      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 */
@@ -641,17 +668,19 @@ _Jv_PrepareClass(jclass klass)
       if (orig_meth == 0)
        {
          // new methods that are final, also don't go in the vtable
-         if ((this_meth->accflags & FINAL) != 0)
+         if ((this_meth->accflags & Modifier::FINAL) != 0)
            continue;
 
          new_method_count += 1;
          continue;
        }
 
-      if ((orig_meth->accflags & (STATIC|PRIVATE|FINAL)) != 0
-         || ((orig_meth->accflags & ABSTRACT) == 0
-             && (this_meth->accflags & ABSTRACT) != 0
-             && (klass->accflags & ABSTRACT) == 0))
+      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 ();
@@ -673,11 +702,22 @@ _Jv_PrepareClass(jclass klass)
     _Jv_AllocBytesChecked (sizeof (_Jv_VTable) 
                           + (sizeof (void*) * (vtable_count)));
   vtable->clas = clz;
+  vtable->gc_descr = _Jv_BuildGCDescr(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. */
+    if (effective_superclass && effective_superclass->vtable)
+      memcpy ((void*)&vtable->method[0],
+             (void*)&effective_superclass->vtable->method[0],
+             sizeof (void*) * effective_superclass->vtable_method_count);
+  }
 
   /* now, install our own vtable entries, reprise... */
   for (int i = 0; i < clz->method_count; i++)
@@ -688,12 +728,12 @@ _Jv_PrepareClass(jclass klass)
                                            this_meth->name,
                                            this_meth->signature);
 
-      if (index == 0)
+      if (index == METHOD_NOT_THERE)
        throw_internal_error ("method now found in own class");
 
-      if (index != -1)
+      if (index != METHOD_INACCESSIBLE)
        {
-         if (index > clz->vtable_method_count+1)
+         if (index > clz->vtable_method_count)
            throw_internal_error ("vtable problem...");
 
          if (clz->interpreted_methods[i] == 0)
@@ -715,6 +755,8 @@ _Jv_PrepareClass(jclass klass)
 void
 _Jv_InitField (jobject obj, jclass klass, int index)
 {
+  using namespace java::lang::reflect;
+
   if (obj != 0 && klass == 0)
     klass = obj->getClass ();
 
@@ -738,12 +780,12 @@ _Jv_InitField (jobject obj, jclass klass, int index)
   if (! field->isResolved ())
     throw_internal_error ("initializing unresolved field");
 
-  if (obj==0 && ((field->flags & STATIC) == 0))
+  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
     throw_internal_error ("initializing non-static field with no object");
 
   void *addr = 0;
 
-  if ((field->flags & STATIC) != 0)
+  if ((field->flags & Modifier::STATIC) != 0)
     addr = (void*) field->u.addr;
   else
     addr = (void*) (((char*)obj) + field->u.boffset);
@@ -754,23 +796,24 @@ _Jv_InitField (jobject obj, jclass klass, int index)
       {
        _Jv_MonitorEnter (clz);
        jstring str;
-       str = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) pool->data[init]);
-       pool->data[init] = (void *) str;
+       str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
+       pool->data[init].string = str;
        pool->tags[init] = JV_CONSTANT_ResolvedString;
        _Jv_MonitorExit (clz);
       }
       /* fall through */
 
     case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &StringClass || field->type == &ObjectClass))
+      if (! (field->type == &StringClass
+            || field->type == &java::lang::Class::class$))
        throw_class_format_error ("string initialiser to non-string field");
 
-      *(jstring*)addr = *(jstring*) (pool->data + init);
+      *(jstring*)addr = pool->data[init].string;
       break;
 
     case JV_CONSTANT_Integer:
       {
-       int value = *(jint*)(pool->data + init);
+       int value = pool->data[init].i;
 
        if (field->type == JvPrimClass (boolean))
          *(jboolean*)addr = (jboolean)value;
@@ -796,21 +839,21 @@ _Jv_InitField (jobject obj, jclass klass, int index)
       if (field->type != JvPrimClass (long))
        throw_class_format_error ("erroneous field initializer");
 
-      memcpy (addr, pool->data+init, 8);
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
       break;
 
     case JV_CONSTANT_Float:
       if (field->type != JvPrimClass (float))
        throw_class_format_error ("erroneous field initializer");
 
-      memcpy (addr, pool->data+init, 4);
+      *(jfloat*)addr = pool->data[init].f;
       break;
 
     case JV_CONSTANT_Double:
       if (field->type != JvPrimClass (double))
        throw_class_format_error ("erroneous field initializer");
 
-      memcpy (addr, pool->data+init, 8);
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
       break;
 
     default:
@@ -871,6 +914,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;
@@ -943,7 +996,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;
 
@@ -985,9 +1039,19 @@ 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;
 }
 
+#if FFI_NATIVE_RAW_API
+#   define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure
+#   define FFI_RAW_SIZE ffi_raw_size
+#else
+#   define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure
+#   define FFI_RAW_SIZE ffi_java_raw_size
+#endif
 
 /* we put this one here, and not in interpret.cc because it
  * calls the utility routines count_arguments 
@@ -1002,12 +1066,15 @@ typedef struct {
 
 typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
 
-void* _Jv_InterpMethod::ncode ()
+void *
+_Jv_InterpMethod::ncode ()
 {
+  using namespace java::lang::reflect;
+
   if (self->ncode != 0)
     return self->ncode;
 
-  jboolean staticp = (self->accflags & STATIC) != 0;
+  jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
   int arg_count = count_arguments (self->signature, staticp);
 
   ncode_closure *closure =
@@ -1018,13 +1085,16 @@ void* _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);
+  args_raw_size = FFI_RAW_SIZE (&closure->cif);
+
+  JvAssert ((self->accflags & Modifier::NATIVE) == 0);
 
-  if ((self->accflags & SYNCHRONIZED) != 0)
+  if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
     {
       if (staticp)
        fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
@@ -1036,16 +1106,78 @@ void* _Jv_InterpMethod::ncode ()
       fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
     }
 
-  ffi_prep_raw_closure (&closure->closure,
-                    &closure->cif, 
-                    fun,
-                    (void*)this);
+  FFI_PREP_RAW_CLOSURE (&closure->closure,
+                       &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*
@@ -1065,7 +1197,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;
@@ -1098,4 +1231,4 @@ throw_internal_error (char *msg)
 }
 
 
-#endif
+#endif /* INTERPRETER */