This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[BC ABI] A few fixes
- From: Andrew Haley <aph at redhat dot com>
- To: java-patches at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Wed, 26 May 2004 14:48:49 +0100
- Subject: [BC ABI] A few fixes
A few compiler changes.
We weren't generating vtable entries for final methods: we need to do
that, because a final mathod might be changed to be non-final.
Interface calls weren't binary compatible: I've reverted to the old
way we did this, with method lookup at runtime. This is a performance
regression but a correctness improvement. I expect this fix to be
short-lived.
I found a bug in jcf-parse.c that can blow up the compiler with
infinite recursion. I've never seen this happen outside the
gcj-abi-2-dev-branch, so I guess it's provoked by the changes there.
Maybe this patch should go into the trunk.
Andrew.
2004-05-26 Andrew Haley <aph@redhat.com>
* jcf-parse.c (load_class): Don't try to read a class that we've
already read.
* expr.c (build_invokeinterface): Use the old-fashioned way of
doing indirect dispatch: look up interfaces by name.
* java-tree.h (enum java_tree_index): Add
JTI_SOFT_LOOKUPINTERFACEMETHODBYNAME_NODE
* gjavah.c (print_method_info): Final methods have vtable entries,
so gjavah needs to output them.
* class.c (layout_class_method): Generate vtable entries for final
methods.
* parse.y (invocation_mode): Use INVOKE_VIRTUAL for indirect
dispatch, even if a method is final.
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.180.2.1
diff -c -2 -p -r1.180.2.1 class.c
*** class.c 16 Apr 2004 12:47:15 -0000 1.180.2.1
--- class.c 26 May 2004 13:36:32 -0000
*************** layout_class_method (tree this_class, tr
*** 2210,2218 ****
method_decl, method_decl);
}
! else if (! METHOD_FINAL (method_decl)
! && ! METHOD_PRIVATE (method_decl)
! && ! CLASS_FINAL (TYPE_NAME (this_class))
&& dtable_count)
{
DECL_VINDEX (method_decl) = dtable_count;
dtable_count = fold (build (PLUS_EXPR, integer_type_node,
--- 2210,2226 ----
method_decl, method_decl);
}
! else if (this_class == object_type_node
! && (METHOD_FINAL (method_decl)
! || METHOD_PRIVATE (method_decl)))
! {
! /* We don't generate vtable entries for final Object
! methods. This is simply to save space, since every
! object would otherwise have to define them. */
! }
! else if (! METHOD_PRIVATE (method_decl)
&& dtable_count)
{
+ /* We generate vtable entries for final methods because they
+ may one day be changed to non-final. */
DECL_VINDEX (method_decl) = dtable_count;
dtable_count = fold (build (PLUS_EXPR, integer_type_node,
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.178
diff -c -2 -p -r1.178 decl.c
*** decl.c 5 Feb 2004 22:07:32 -0000 1.178
--- decl.c 26 May 2004 13:36:33 -0000
*************** java_init_decl_processing (void)
*** 862,866 ****
build_function_type (ptr_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE);
!
t = tree_cons (NULL_TREE, object_ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
--- 862,873 ----
build_function_type (ptr_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE);
!
! t = tree_cons (NULL_TREE, ptr_type_node,
! tree_cons (NULL_TREE, ptr_type_node,
! tree_cons (NULL_TREE, ptr_type_node, endlink)));
! soft_lookupinterfacemethodbyname_node
! = builtin_function ("_Jv_LookupInterfaceMethod",
! build_function_type (ptr_type_node, t),
! 0, NOT_BUILT_IN, NULL, NULL_TREE);
t = tree_cons (NULL_TREE, object_ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.185.2.1
diff -c -2 -p -r1.185.2.1 expr.c
*** expr.c 16 Apr 2004 12:47:15 -0000 1.185.2.1
--- expr.c 26 May 2004 13:36:34 -0000
*************** build_invokeinterface (tree dtable, tree
*** 1999,2003 ****
tree idx;
tree meth;
- tree otable_index;
int i;
--- 1999,2002 ----
*************** build_invokeinterface (tree dtable, tree
*** 2021,2030 ****
if (flag_indirect_dispatch)
{
! otable_index =
! build_int_2 (get_symbol_table_index
! (method, &TYPE_OTABLE_METHODS (output_class)), 0);
! idx =
! build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
! otable_index);
}
else
--- 2020,2049 ----
if (flag_indirect_dispatch)
{
! // FIXME: We look up the interface by name every time we make an
! // interface call. There is an interface cache in the runtime
! // library, but even so this sucks.
!
! // PR 12760 says: "... the best solution would be to make the
! // "otable" for interfaces have a pair of values - interface
! // where the target method is found in addition to offset. Both
! // of these would be passed to _Jv_LookupInterfaceMethodIdx."
! // However, other Java implementations seem to resolve
! // interfaces lazily, so there is some compatibility advantage
! // in doing things this way.
!
! tree method_signature = TYPE_SIGNATURE (TREE_TYPE (method));
! tree method_name = DECL_NAME (method);
!
! lookup_arg = build_tree_list (NULL_TREE,
! (build_utf8_ref
! (unmangle_classname
! (IDENTIFIER_POINTER(method_signature),
! IDENTIFIER_LENGTH(method_signature)))));
! lookup_arg = tree_cons (NULL_TREE, dtable,
! tree_cons (NULL_TREE, build_utf8_ref (method_name),
! lookup_arg));
! return build (CALL_EXPR, ptr_type_node,
! build_address_of (soft_lookupinterfacemethodbyname_node),
! lookup_arg, NULL_TREE);
}
else
Index: gjavah.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/gjavah.c,v
retrieving revision 1.113
diff -c -2 -p -r1.113 gjavah.c
*** gjavah.c 20 Mar 2004 14:03:34 -0000 1.113
--- gjavah.c 26 May 2004 13:36:34 -0000
*************** static JCF_u2 last_access;
*** 112,115 ****
--- 112,118 ----
((Method) & ACC_NATIVE)
+ #define METHOD_IS_PRIVATE(Class, Method) \
+ (((Method) & ACC_PRIVATE) != 0)
+
/* We keep a linked list of all method names we have seen. This lets
us determine if a method name and a field name are in conflict. */
*************** print_method_info (FILE *stream, JCF* jc
*** 880,884 ****
if ((flags & ACC_STATIC))
fputs ("static ", out);
! else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
{
/* Don't print `virtual' if we have a constructor. */
--- 883,887 ----
if ((flags & ACC_STATIC))
fputs ("static ", out);
! else if (! METHOD_IS_PRIVATE (jcf->access_flags, flags))
{
/* Don't print `virtual' if we have a constructor. */
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.197.2.1
diff -c -2 -p -r1.197.2.1 java-tree.h
*** java-tree.h 16 Apr 2004 12:47:15 -0000 1.197.2.1
--- java-tree.h 26 May 2004 13:36:35 -0000
*************** enum java_tree_index
*** 399,402 ****
--- 399,403 ----
JTI_SOFT_MONITOREXIT_NODE,
JTI_SOFT_LOOKUPINTERFACEMETHOD_NODE,
+ JTI_SOFT_LOOKUPINTERFACEMETHODBYNAME_NODE,
JTI_SOFT_LOOKUPJNIMETHOD_NODE,
JTI_SOFT_GETJNIENVNEWFRAME_NODE,
*************** extern GTY(()) tree java_global_trees[JT
*** 658,661 ****
--- 659,664 ----
#define soft_lookupinterfacemethod_node \
java_global_trees[JTI_SOFT_LOOKUPINTERFACEMETHOD_NODE]
+ #define soft_lookupinterfacemethodbyname_node \
+ java_global_trees[JTI_SOFT_LOOKUPINTERFACEMETHODBYNAME_NODE]
#define soft_lookupjnimethod_node \
java_global_trees[JTI_SOFT_LOOKUPJNIMETHOD_NODE]
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.158.4.1
diff -c -2 -p -r1.158.4.1 jcf-parse.c
*** jcf-parse.c 16 Apr 2004 12:47:15 -0000 1.158.4.1
--- jcf-parse.c 26 May 2004 13:36:35 -0000
*************** load_class (tree class_or_name, int verb
*** 588,591 ****
--- 588,599 ----
char *separator;
+ /* We've already loaded it. */
+ if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
+ {
+ tree type_decl = IDENTIFIER_CLASS_VALUE (name);
+ if (CLASS_PARSED_P (TREE_TYPE (type_decl)))
+ break;
+ }
+
if ((class_loaded = read_class (name)))
break;
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.474.2.1
diff -c -2 -p -r1.474.2.1 parse.y
*** parse.y 16 Apr 2004 12:47:14 -0000 1.474.2.1
--- parse.y 26 May 2004 13:36:40 -0000
*************** invocation_mode (tree method, int super)
*** 10926,10934 ****
return INVOKE_STATIC;
! if (access & ACC_FINAL || access & ACC_PRIVATE)
return INVOKE_NONVIRTUAL;
! if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method))))
! return INVOKE_NONVIRTUAL;
if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))))
--- 10926,10943 ----
return INVOKE_STATIC;
! if (access & ACC_PRIVATE)
return INVOKE_NONVIRTUAL;
! /* Binary compatibility: just because it's final today, that doesn't
! mean it'll be final tomorrow. */
! if (! flag_indirect_dispatch
! || DECL_CONTEXT (method) == object_type_node)
! {
! if (access & ACC_FINAL)
! return INVOKE_NONVIRTUAL;
!
! if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method))))
! return INVOKE_NONVIRTUAL;
! }
if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))))