This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: FYI: partial fix for PR java/20215


I'm checking this in on the trunk and the 4.0 branch.

When linking a field, we weren't properly looking at types, as pointed
out in PR 20215.  This fixes the runtime part of this bug by
rearranging how we link fields.  It is probably somewhat less
efficient, but now at least it is correct.

Tested on x86 FC2, and also against the test case in the PR and the
"eclipse startup smoke test".

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	PR java/20215:
	* include/jvm.h (_Jv_Linker::find_field_helper): Updated.
	* link.cc (find_field_helper): Added 'type' argument.
	(find_field): Updated.

Index: link.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/link.cc,v
retrieving revision 1.10
diff -u -r1.10 link.cc
--- link.cc 19 Feb 2005 05:17:14 -0000 1.10
+++ link.cc 6 Mar 2005 07:13:02 -0000
@@ -100,6 +100,7 @@
 // superclasses and interfaces.
 _Jv_Field *
 _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name,
+			       _Jv_Utf8Const *type_name,
 			       jclass *declarer)
 {
   while (search)
@@ -108,7 +109,21 @@
       for (int i = 0; i < search->field_count; ++i)
 	{
 	  _Jv_Field *field = &search->fields[i];
-	  if (_Jv_equalUtf8Consts (field->name, name))
+	  if (! _Jv_equalUtf8Consts (field->name, name))
+	    continue;
+
+	  if (! field->isResolved ())
+	    resolve_field (field, search->loader);
+
+	  // Note that we compare type names and not types.  This is
+	  // bizarre, but we do it because we want to find a field
+	  // (and terminate the search) if it has the correct
+	  // descriptor -- but then later reject it if the class
+	  // loader check results in different classes.  We can't just
+	  // pass in the descriptor and check that way, because when
+	  // the field is already resolved there is no easy way to
+	  // find its descriptor again.
+	  if (_Jv_equalUtf8Consts (type_name, field->type->name))
 	    {
 	      *declarer = search;
 	      return field;
@@ -119,7 +134,7 @@
       for (int i = 0; i < search->interface_count; ++i)
 	{
 	  _Jv_Field *result = find_field_helper (search->interfaces[i], name,
-						 declarer);
+						 type_name, declarer);
 	  if (result)
 	    return result;
 	}
@@ -155,23 +170,14 @@
 			_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);
-    }
+  // FIXME: this allocates a _Jv_Utf8Const each time.  We should make
+  // it cheaper.
+  jclass 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);
+  _Jv_Field *the_field = find_field_helper (owner, field_name,
+					    field_type->name, &found_class);
 
   if (the_field == 0)
     {
@@ -186,12 +192,11 @@
 
   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)
+      // Note that the field returned by find_field_helper is always
+      // resolved.  There's no point checking class loaders here,
+      // since we already did the work to look up all the types.
+      // FIXME: being lazy here would be nice.
+      if (the_field->type != field_type)
 	throw new java::lang::LinkageError
 	  (JvNewStringLatin1 
 	   ("field type mismatch with different loaders"));
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.77
diff -u -r1.77 jvm.h
--- include/jvm.h 19 Feb 2005 01:16:30 -0000 1.77
+++ include/jvm.h 6 Mar 2005 07:13:03 -0000
@@ -250,7 +250,8 @@
 class _Jv_Linker
 {
 private:
-  static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, jclass *);
+  static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, _Jv_Utf8Const *,
+				      jclass *);
   static _Jv_Field *find_field(jclass, jclass, _Jv_Utf8Const *,
 			       _Jv_Utf8Const *);
   static void prepare_constant_time_tables(jclass);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]