This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Java: Local function pointer aliases for method metadata
- From: Bryce McKinlay <mckinlay at redhat dot com>
- To: java-patches at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Tue, 17 Aug 2004 21:34:48 -0400
- Subject: 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