This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[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))))


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