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]

Re: PING: Reflection doesn't work across interfaces


Andrew Haley wrote:

Subject:
Reflection doesn't work across interfaces

Yes, really.

This is pretty amazing, but I've discovered that Method.invoke()
doesn't work when the Method is in an interface.


Ugh. I must have introduced this a few months back when I changed Method.invoke() to use vtables. Sorry about that.

--- 474,491 ----
     {
       _Jv_VTable *vtable = *(_Jv_VTable **) obj;
!       if (iface == NULL)
! 	ncode = vtable->get_method (meth->index);
!       else
! 	{
! 	  /* Okay, here's how it goes.  We want to know the method
! 	     offset in the list of methods declared by an interface,
! 	     starting at 1.  The offset in the method is the vtable
! 	     offset, not the offset in the interface, so we subtract
! 	     that.  We add 1 because we count interface methods
! 	     beginning at 1.  I think this is because of the initial
! 	     gc descriptor in the vtable.  */
! 	  jint offset = meth->index - JvGetFirstMethod (iface)->index + 1;
! 	  ncode = _Jv_LookupInterfaceMethodIdx (vtable->clas, iface, offset);
! 	}
     }
   else

I think it would be better to just have the compiler put the interface method's index in the meth->index field here, rather than have the runtime do fixups on a hypothetical vtable offset. How does the patch below look? Otherwise, your patch looks fine to me. Obviously the invocation code has become a bit of a mess and could really use some refactoring, for example to clearly separate the lookup and argument prep/execution stages, but this looks ok for now.

Regards

Bryce.

2004-04-12  Bryce McKinlay  <mckinlay@redhat.com>

	* class.c (get_interface_method_index): New function. Return dispatch 
	index for interface method.
	(make_method_value): For interface methods, set index field to
	iface dispatch index, not DECL_VINDEX.
	* expr.c (build_invokeinterface): Use get_interface_method_index.

Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.180
diff -u -r1.180 class.c
--- class.c	20 Mar 2004 14:03:33 -0000	1.180
+++ class.c	12 Apr 2004 22:33:56 -0000
@@ -1250,13 +1287,20 @@
   int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED;
 
   if (!flag_indirect_dispatch && DECL_VINDEX (mdecl) != NULL_TREE)
-    index = DECL_VINDEX (mdecl);
+    {
+      tree class_decl = DECL_CONTEXT (mdecl);
+      /* For interface methods, the index field contains the itable index, not vtable offset. */
+      if (CLASS_INTERFACE (TYPE_NAME (class_decl)))
+	index = build_int_2 (get_interface_method_index (mdecl, class_decl), 0);
+      else 
+	index = DECL_VINDEX (mdecl);
+    }
   else
     index = integer_minus_one_node;
 
@@ -2131,6 +2175,23 @@
 					method_decl, dtable_count);
 
   TYPE_NVIRTUALS (this_class) = dtable_count;
+}
+
+/* Return the index of METHOD in INTERFACE.  This index begins at 1 and is used as an
+   argument for _Jv_LookupInterfaceMethodIdx(). */
+int
+get_interface_method_index (tree method, tree interface)
+{
+  tree meth;
+  int i = 1;
+
+  for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
+    {
+      if (meth == method)
+	return i;
+      if (meth == NULL_TREE)
+	abort ();
+    }
 }
 
 /* Lay METHOD_DECL out, returning a possibly new value of
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.185
diff -u -r1.185 expr.c
--- expr.c	30 Mar 2004 19:19:06 -0000	1.185
+++ expr.c	12 Apr 2004 22:33:57 -0000
@@ -1974,17 +1974,7 @@
     }
   else
     {
-      i = 1;
-      for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
-	{
-	  if (meth == method)
-            {
-	      idx = build_int_2 (i, 0);
-	      break;
-	    }
-	  if (meth == NULL_TREE)
-	    abort ();
-	}
+      idx = build_int_2 (get_interface_method_index (method, interface), 0);
     }
 
   lookup_arg = tree_cons (NULL_TREE, dtable,
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.197
diff -u -r1.197 java-tree.h
--- java-tree.h	19 Mar 2004 23:10:55 -0000	1.197
+++ java-tree.h	12 Apr 2004 22:35:26 -0000
@@ -1149,6 +1149,7 @@
 extern tree parse_signature_string (const unsigned char *, int);
 extern tree get_type_from_signature (tree);
 extern void layout_class (tree);
+extern int get_interface_method_index (tree, tree);
 extern tree layout_class_method (tree, tree, tree, tree);
 extern void layout_class_methods (tree);
 extern tree build_class_ref (tree);

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