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]

Java: Local function pointer aliases for method metadata


This patch changes the function pointer (ncode) entry in libjava's _Jv_Method struct to use a local alias decl rather than refer directly to the public decl for the function. Without this, the method pointers can in some circumstances end up pointing at PLT entries, which makes stack traces fail. The problem still exists for CNI functions, but this patch solves it for the common cases. We'll eventually fix it for CNI also with a change to the way CNI methods are registered as part of the BC-ABI. make_local_function_alias is based on make_alias_for_thunk from the C++ front end.

Making this change revealed problems with the way anonymous class constructors are emitted when compiling source code. At -O3, we'd get a link error because the anonymous constructor would be removed after inlining, but the alias wasn't. This was because layout_class_method was not being called on the synthetic constructor created for the anonymous class - it might not be created until after the anonymous class is laid out (thanks to aph for helping to track this down). The solution is to simply call layout_class_method as soon as the constructor is created. This also allows us to remove some special handling for anonymous constructors that had appeared elsewhere.

Bootstrapped/tested on i686. No regressions. OK to commit?

Regards

Bryce

2004-08-17  Bryce McKinlay  <mckinlay@redhat.com>

	* class.c (make_local_function_alias): New function. Create local
	alias for public method DECL.
	(make_method_value): Use make_local_function_alias.
	* parse.y (craft_constructor): Don't special-case anonymous classes.
	Always set ctor_name to init_identifier_node.
	(lookup_method_invoke): Call layout_class_method when creating
	anonymous class constructor.

Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.202
diff -u -r1.202 class.c
--- class.c	15 Aug 2004 15:45:29 -0000	1.202
+++ class.c	18 Aug 2004 01:30:10 -0000
@@ -1198,6 +1198,50 @@
   abort ();
 }
 
+/* Create a private alias for METHOD. Using this alias instead of the method
+decl ensures that ncode entries in the method table point to the real function 
+at runtime, not a PLT entry.  */
+
+static tree
+make_local_function_alias (tree method)
+{
+  tree alias;
+  char *buf, *ptr;
+  const char *alias_id = "LALIAS_";
+  int name_len;
+  
+  /* Make the alias name by prepending alias_id.  */
+  name_len = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (method));
+  ptr = buf = alloca (strlen (alias_id) + name_len + 1);
+  strcpy (ptr, alias_id);
+  ptr += strlen (alias_id);
+  strcpy (ptr, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));
+  ptr += name_len;
+  *ptr = '\0';
+  
+  alias = build_decl (FUNCTION_DECL, get_identifier (buf),
+		      TREE_TYPE (method));
+  DECL_CONTEXT (alias) = NULL;
+  TREE_READONLY (alias) = TREE_READONLY (method);
+  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (method);
+  TREE_PUBLIC (alias) = 0;
+  DECL_EXTERNAL (alias) = 0;
+  DECL_ARTIFICIAL (alias) = 1;
+  DECL_NO_STATIC_CHAIN (alias) = 1;
+  DECL_INLINE (alias) = 0;
+  DECL_DECLARED_INLINE_P (alias) = 0;
+  DECL_INITIAL (alias) = error_mark_node;
+  TREE_ADDRESSABLE (alias) = 1;
+  TREE_USED (alias) = 1;
+  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
+  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
+  if (!flag_syntax_only)
+    assemble_alias (alias, DECL_ASSEMBLER_NAME (method));
+  return alias;
+}
+
+/** Make reflection data (_Jv_Field) for field FDECL. */
+
 static tree
 make_field_value (tree fdecl)
 {
@@ -1242,6 +1286,8 @@
   return finit;
 }
 
+/** Make reflection data (_Jv_Method) for method MDECL. */
+
 static tree
 make_method_value (tree mdecl)
 {
@@ -1265,7 +1311,8 @@
 
   code = null_pointer_node;
   if (DECL_RTL_SET_P (mdecl))
-    code = build1 (ADDR_EXPR, nativecode_ptr_type_node, mdecl);
+    code = build1 (ADDR_EXPR, nativecode_ptr_type_node, 
+		   make_local_function_alias (mdecl));
   START_RECORD_CONSTRUCTOR (minit, method_type_node);
   PUSH_FIELD_VALUE (minit, "name",
 		    build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ?
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.502
diff -u -r1.502 parse.y
--- parse.y	17 Aug 2004 12:51:01 -0000	1.502
+++ parse.y	18 Aug 2004 01:30:12 -0000
@@ -5422,13 +5422,7 @@
   tree decl, ctor_name;
   char buffer [80];
 
-  /* The constructor name is <init> unless we're dealing with an
-     anonymous class, in which case the name will be fixed after having
-     be expanded. */
-  if (ANONYMOUS_CLASS_P (class_type))
-    ctor_name = DECL_NAME (class_decl);
-  else
-    ctor_name = init_identifier_node;
+  ctor_name = init_identifier_node;
 
   /* If we're dealing with an inner class constructor, we hide the
      this$<n> decl in the name field of its parameter declaration. */
@@ -10930,12 +10924,10 @@
 
   if (lc && ANONYMOUS_CLASS_P (class))
     {
-      tree saved_current_class;
       tree mdecl = craft_constructor (TYPE_NAME (class), atl);
-      saved_current_class = current_class;
-      current_class = class;
-      fix_constructors (mdecl);
-      current_class = saved_current_class;
+      /* Other methods in the anonymous class may already be laid out, so 
+         explicitly lay it out here.  */
+      layout_class_method (class, CLASSTYPE_SUPER (class), mdecl, NULL_TREE);
     }
 
   /* Find all candidates and then refine the list, searching for the

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