This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: PING: Reflection doesn't work across interfaces
- From: Bryce McKinlay <mckinlay at redhat dot com>
- To: Andrew Haley <aph at redhat dot com>
- Cc: java-patches at gcc dot gnu dot org
- Date: Mon, 12 Apr 2004 18:43:40 -0400
- Subject: Re: PING: Reflection doesn't work across interfaces
- References: <16490.51964.646352.831451@cuddles.cambridge.redhat.com>
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);