OSDN Git Service

PR libgcj/18868:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Jan 2005 19:21:46 +0000 (19:21 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Jan 2005 19:21:46 +0000 (19:21 +0000)
* include/jvm.h (_Jv_Linker::find_field): Declare.
(_Jv_Linker::find_field_helper): Likewise.
* link.cc (find_field_helper): New method.
(find_field): Likewise.
(resolve_pool_entry): Use it.  Throw NoSuchFieldError when field
not found.
(link_symbol_table): Use find_field.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@93151 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/include/jvm.h
libjava/link.cc

index a0d212c..17f4d64 100644 (file)
@@ -1,3 +1,14 @@
+2005-01-10  Tom Tromey  <tromey@redhat.com>
+
+       PR libgcj/18868:
+       * include/jvm.h (_Jv_Linker::find_field): Declare.
+       (_Jv_Linker::find_field_helper): Likewise.
+       * link.cc (find_field_helper): New method.
+       (find_field): Likewise.
+       (resolve_pool_entry): Use it.  Throw NoSuchFieldError when field
+       not found.
+       (link_symbol_table): Use find_field.
+
 2005-01-10  Michael Koch  <konqueror@gmx.de>
 
        PR libgcj/18014
index ff2c9b1..52471bf 100644 (file)
@@ -1,6 +1,6 @@
 // jvm.h - Header file for private implementation information. -*- c++ -*-
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -250,6 +250,9 @@ namespace gcj
 class _Jv_Linker
 {
 private:
+  static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, jclass *);
+  static _Jv_Field *find_field(jclass, jclass, _Jv_Utf8Const *,
+                              _Jv_Utf8Const *);
   static void prepare_constant_time_tables(jclass);
   static jshort get_interfaces(jclass, _Jv_ifaces *);
   static void link_symbol_table(jclass);
index 46d8586..b0559c4 100644 (file)
@@ -1,6 +1,6 @@
 // link.cc - Code for linking and resolving classes and pool entries.
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -94,6 +94,109 @@ _Jv_Linker::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader)
     }
 }
 
+// A helper for find_field that knows how to recursively search
+// superclasses and interfaces.
+_Jv_Field *
+_Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name,
+                              jclass *declarer)
+{
+  while (search)
+    {
+      // From 5.4.3.2.  First search class itself.
+      for (int i = 0; i < search->field_count; ++i)
+       {
+         _Jv_Field *field = &search->fields[i];
+         if (_Jv_equalUtf8Consts (field->name, name))
+           {
+             *declarer = search;
+             return field;
+           }
+       }
+
+      // Next search direct interfaces.
+      for (int i = 0; i < search->interface_count; ++i)
+       {
+         _Jv_Field *result = find_field_helper (search->interfaces[i], name,
+                                                declarer);
+         if (result)
+           return result;
+       }
+
+      // Now search superclass.
+      search = search->superclass;
+    }
+
+  return NULL;
+}
+
+// Find a field.
+// KLASS is the class that is requesting the field.
+// OWNER is the class in which the field should be found.
+// FIELD_TYPE_NAME is the type descriptor for the field.
+// This function does the class loader type checks, and
+// also access checks.  Returns the field, or throws an
+// exception on error.
+_Jv_Field *
+_Jv_Linker::find_field (jclass klass, jclass owner,
+                       _Jv_Utf8Const *field_name,
+                       _Jv_Utf8Const *field_type_name)
+{
+  jclass field_type = 0;
+
+  if (owner->loader != klass->loader)
+    {
+      // FIXME: The implementation of this function
+      // (_Jv_FindClassFromSignature) will generate an instance of
+      // _Jv_Utf8Const for each call if the field type is a class name
+      // (Lxx.yy.Z;).  This may be too expensive to do for each and
+      // every fieldref being resolved.  For now, we fix the problem
+      // by only doing it when we have a loader different from the
+      // class declaring the field.
+      field_type = _Jv_FindClassFromSignature (field_type_name->chars(),
+                                              klass->loader);
+    }
+
+  jclass found_class = 0;
+  _Jv_Field *the_field = find_field_helper (owner, field_name, &found_class);
+
+  if (the_field == 0)
+    {
+      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->chars()));
+      sb->append(JvNewStringLatin1(" was not found."));
+      throw new java::lang::NoSuchFieldError (sb->toString());
+    }
+
+  if (_Jv_CheckAccess (klass, found_class, the_field->flags))
+    {
+      // Resolve the field using the class' own loader if necessary.
+
+      if (!the_field->isResolved ())
+       resolve_field (the_field, found_class->loader);
+
+      if (field_type != 0 && the_field->type != field_type)
+       throw new java::lang::LinkageError
+         (JvNewStringLatin1 
+          ("field type mismatch with different loaders"));
+    }
+  else
+    {
+      java::lang::StringBuffer *sb
+       = new java::lang::StringBuffer ();
+      sb->append(klass->getName());
+      sb->append(JvNewStringLatin1(": "));
+      sb->append(found_class->getName());
+      sb->append(JvNewStringLatin1("."));
+      sb->append(_Jv_NewStringUtf8Const (field_name));
+      throw new java::lang::IllegalAccessError(sb->toString());
+    }
+
+  return the_field;
+}
+
 _Jv_word
 _Jv_Linker::resolve_pool_entry (jclass klass, int index)
 {
@@ -173,72 +276,8 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int 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
-       // _Jv_Utf8Const for each call if the field type is a class name
-       // (Lxx.yy.Z;).  This may be too expensive to do for each and
-       // every fieldref being resolved.  For now, we fix the problem by
-       // only doing it when we have a loader different from the class
-       // declaring the field.
-
-       jclass field_type = 0;
-
-       if (owner->loader != klass->loader)
-         field_type = _Jv_FindClassFromSignature (field_type_name->chars(),
-                                                  klass->loader);
-      
-       _Jv_Field* the_field = 0;
-
-       for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
-         {
-           for (int i = 0;  i < cls->field_count;  i++)
-             {
-               _Jv_Field *field = &cls->fields[i];
-               if (! _Jv_equalUtf8Consts (field->name, field_name))
-                 continue;
-
-               if (_Jv_CheckAccess (klass, cls, field->flags))
-                 {
-                   // Resolve the field using the class' own loader if
-                   // necessary.
-
-                   if (!field->isResolved ())
-                     resolve_field (field, cls->loader);
-
-                   if (field_type != 0 && field->type != field_type)
-                     throw new java::lang::LinkageError
-                       (JvNewStringLatin1 
-                        ("field type mismatch with different loaders"));
-
-                   the_field = field;
-                   goto end_of_field_search;
-                 }
-               else
-                 {
-                   java::lang::StringBuffer *sb
-                     = new java::lang::StringBuffer ();
-                   sb->append(klass->getName());
-                   sb->append(JvNewStringLatin1(": "));
-                   sb->append(cls->getName());
-                   sb->append(JvNewStringLatin1("."));
-                   sb->append(_Jv_NewStringUtf8Const (field_name));
-                   throw new java::lang::IllegalAccessError(sb->toString());
-                 }
-             }
-         }
-
-      end_of_field_search:
-       if (the_field == 0)
-         {
-           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->chars()));
-           sb->append(JvNewStringLatin1(" was not found."));
-           throw
-             new java::lang::IncompatibleClassChangeError (sb->toString());
-         }
+       _Jv_Field *the_field = find_field (klass, owner, field_name,
+                                          field_type_name);
 
        pool->data[index].field = the_field;
        pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
@@ -296,7 +335,7 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index)
            ifaces.list = (jclass *) _Jv_Malloc (ifaces.len
                                                 * sizeof (jclass *));
 
-           get_interfaces (owner, &ifaces);      
+           get_interfaces (owner, &ifaces);
 
            for (int i = 0; i < ifaces.count; i++)
              {
@@ -885,55 +924,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
          continue;
        }
 
-      // try fields
+      // Try fields.
       {
-       _Jv_Field *the_field = NULL;
-
        wait_for_state(target_class, JV_STATE_PREPARED);
-       for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
-         {
-           for (int i = 0; i < cls->field_count; i++)
-             {
-               _Jv_Field *field = &cls->fields[i];
-               if (! _Jv_equalUtf8Consts (field->name, sym.name))
-                 continue;
-
-               // FIXME: What access checks should we perform here?
-//             if (_Jv_CheckAccess (klass, cls, field->flags))
-//               {
-
-               if (!field->isResolved ())
-                 resolve_field (field, cls->loader);
-
-//             if (field_type != 0 && field->type != field_type)
-//               throw new java::lang::LinkageError
-//                 (JvNewStringLatin1 
-//                  ("field type mismatch with different loaders"));
-
-               the_field = field;
-               if (debug_link)
-                 fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s)\n",
-                          (int)index,
-                          (int)field->u.boffset,
-                          (const char*)cls->name->chars(),
-                          cls,
-                          (const char*)field->name->chars());
-               goto end_of_field_search;
-             }
-         }
-      end_of_field_search:
-       if (the_field != NULL)
-         {
-           if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
-             throw new java::lang::IncompatibleClassChangeError;
-           else
-             klass->otable->offsets[index] = the_field->u.boffset;
-         }
+       _Jv_Field *the_field = find_field (klass, target_class,
+                                          sym.name, sym.signature);
+       if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
+         throw new java::lang::IncompatibleClassChangeError;
        else
-         {
-           throw new java::lang::NoSuchFieldError
-             (_Jv_NewStringUtf8Const (sym.name));
-         }
+         klass->otable->offsets[index] = the_field->u.boffset;
       }
     }
 
@@ -1005,48 +1004,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
          continue;
        }
 
-      // try fields
+      // Try fields.
       {
-       _Jv_Field *the_field = NULL;
-
        wait_for_state(target_class, JV_STATE_PREPARED);
-       for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
-         {
-           for (int i = 0; i < cls->field_count; i++)
-             {
-               _Jv_Field *field = &cls->fields[i];
-               if (! _Jv_equalUtf8Consts (field->name, sym.name))
-                 continue;
-
-               // FIXME: What access checks should we perform here?
-//             if (_Jv_CheckAccess (klass, cls, field->flags))
-//               {
-
-               if (!field->isResolved ())
-                 resolve_field (field, cls->loader);
-
-//             if (field_type != 0 && field->type != field_type)
-//               throw new java::lang::LinkageError
-//                 (JvNewStringLatin1 
-//                  ("field type mismatch with different loaders"));
-
-               the_field = field;
-               goto end_of_static_field_search;
-             }
-         }
-      end_of_static_field_search:
-       if (the_field != NULL)
-         {
-           if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
-             klass->atable->addresses[index] = the_field->u.addr;
-           else
-             throw new java::lang::IncompatibleClassChangeError;
-         }
+       _Jv_Field *the_field = find_field (klass, target_class,
+                                          sym.name, sym.signature);
+       if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
+         klass->atable->addresses[index] = the_field->u.addr;
        else
-         {
-           throw new java::lang::NoSuchFieldError
-             (_Jv_NewStringUtf8Const (sym.name));
-         }
+         throw new java::lang::IncompatibleClassChangeError;
       }
     }