This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFC: Java class registration (w/crtstuff change)
- To: gcc-patches at gcc dot gnu dot org, java-patches at gcc dot gnu dot org
- Subject: RFC: Java class registration (w/crtstuff change)
- From: <green at peach dot cygnus dot co dot uk>
- Date: Mon, 30 Jul 2001 01:08:44 -0400
(This patch needs more testing on different platforms, but I'm curious
to hear thoughts, especially w.r.t. crtstuff change - thanks).
This patch changes how java classes are registered at startup time.
All java classes must be registered with the runtime library at
startup time. gcj currently arranges this by creating a constructor
function per file which calls libgcj's _Jv_RegisterClass for each
class defined in that file. Most files in libgcj contain a single
class, although a few contain many more.
This patch improves on this mechanism resulting in smaller programs
through better code density as well as less debug and unwind info.
For example, the stripped libgcj is about 110k smaller on x86 Linux
(almost 3%). This new mechanism is compatible with the old one (both
may be used in a single program).
The new class registration mechanism has the compiler storing pointers
to classes requiring registration in a new section: .jcr (java class
registration). crtbegin and crtend are used to begin the list (with
__JCR_LIST__) and NULL terminate it (at __JCR_END__).
DO_GLOBAL_CTORS_BODY is modified to include a single call to libgcj's
_Jv_RegisterClasses (made available via weak symbol).
This patch enables the new mechanism for ELF systems. The current
mechanism is preserved for other targets.
2001-07-28 Anthony Green <green@redhat.com>
* java/class.c (emit_register_classes): Use assemble_jcr if
possible. Keep the original mechanism as a fallback.
* defaults.h (JCR_SECTION): Define if we have JCR_SECTION_ASM_OP.
* output.h (jcr_section): Declare.
* varasm.c (in_section): Add in_jcr.
(jcr_section): New function.
(assemble_jcr): New function.
* crtstuff.c (__JCR_LIST__): Define.
(__JCR_END__): Define.
(_Jv_RegisterClasses): Declare hook into gcj runtime library.
* gbl-ctors.h (DO_GLOBAL_CTORS_BODY): Register java classes after
calling all constructors.
* config/elfos.h (ASM_OUTPUT_JCR): Define.
(JCR_SECTION_ASM_OP): Define.
Index: gcc/crtstuff.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/crtstuff.c,v
retrieving revision 1.39
diff -p -u -r1.39 crtstuff.c
--- crtstuff.c 2001/05/22 23:01:33 1.39
+++ crtstuff.c 2001/07/30 04:59:42
@@ -415,6 +415,17 @@ STATIC
char __EH_FRAME_BEGIN__[] = { };
#endif /* EH_FRAME_SECTION_ASM_OP */
+#ifdef JCR_SECTION_ASM_OP
+/* Stick a label at the beginning of the java class registration info
+ so we can register them properly. */
+
+asm (JCR_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
+STATIC func_ptr __JCR_LIST__[0] __attribute__ ((__unused__));
+#endif /* JCR_SECTION_ASM_OP */
+
+/* Hook into the gcj runtime library. */
+extern void _Jv_RegisterClasses (void *classes) TARGET_ATTRIBUTE_WEAK;
+
#endif /* defined(CRT_BEGIN) */
#ifdef CRT_END
@@ -543,6 +554,15 @@ typedef unsigned int ui32 __attribute__
asm (EH_FRAME_SECTION_ASM_OP);
STATIC ui32 __FRAME_END__[] __attribute__ ((__unused__)) = { 0 };
#endif /* EH_FRAME_SECTION */
+
+#ifdef JCR_SECTION_ASM_OP
+/* Stick a label at the beginning of the java class registration info
+ so we can register them properly. */
+
+asm (JCR_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
+STATIC func_ptr __JCR_END__[1] __attribute__ ((__unused__))
+ = { (func_ptr) (0) };
+#endif /* JCR_SECTION_ASM_OP */
#endif /* defined(CRT_END) */
Index: gcc/defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.47
diff -p -u -r1.47 defaults.h
--- defaults.h 2001/07/18 20:43:40 1.47
+++ defaults.h 2001/07/30 04:59:42
@@ -222,6 +222,15 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNA
# endif
#endif
+/* If we have no definition for JCR_SECTION, but we do know how to
+ emit assembly for switching tothe .jcr section, call jcr_section to
+ use it. */
+#if !defined (JCR_SECTION)
+# if defined (JCR_SECTION_ASM_OP)
+# define JCR_SECTION() jcr_section ()
+# endif
+#endif
+
/* If we have no definition for UNIQUE_SECTION, but do have the
ability to generate arbitrary sections, construct something
reasonable. */
Index: gcc/gbl-ctors.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gbl-ctors.h,v
retrieving revision 1.8
diff -p -u -r1.8 gbl-ctors.h
--- gbl-ctors.h 2000/07/28 16:08:54 1.8
+++ gbl-ctors.h 2001/07/30 04:59:42
@@ -78,6 +78,8 @@ do { \
for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++); \
for (i = nptrs; i >= 1; i--) \
__CTOR_LIST__[i] (); \
+ if (_Jv_RegisterClasses) \
+ _Jv_RegisterClasses(__JCR_LIST__); \
} while (0)
#endif
Index: gcc/output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.66
diff -p -u -r1.66 output.h
--- output.h 2001/07/16 06:01:39 1.66
+++ output.h 2001/07/30 04:59:42
@@ -163,6 +163,10 @@ extern int in_text_section PARAMS ((voi
extern void eh_frame_section PARAMS ((void));
#endif
+#ifdef JCR_SECTION_ASM_OP
+extern void jcr_section PARAMS ((void));
+#endif
+
#ifdef CTORS_SECTION_ASM_OP
extern void ctors_section PARAMS ((void));
#endif
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.185
diff -p -u -r1.185 varasm.c
--- varasm.c 2001/07/29 02:46:18 1.185
+++ varasm.c 2001/07/30 04:59:43
@@ -189,6 +189,9 @@ static enum in_section { no_section, in_
#ifdef EH_FRAME_SECTION_ASM_OP
, in_eh_frame
#endif
+#ifdef JCR_SECTION_ASM_OP
+ , in_jcr
+#endif
#ifdef EXTRA_SECTIONS
, EXTRA_SECTIONS
#endif
@@ -404,6 +407,18 @@ eh_frame_section ()
}
#endif
+#ifdef JCR_SECTION_ASM_OP
+void
+jcr_section ()
+{
+ if (in_section != in_jcr)
+ {
+ fprintf (asm_out_file, "%s\n", JCR_SECTION_ASM_OP);
+ in_section = in_jcr;
+ }
+}
+#endif /* JCR_SECTION_ASM_OP */
+
/* Switch to the section for function DECL.
If DECL is NULL_TREE, switch to the text section.
@@ -844,6 +859,19 @@ assemble_constructor (name)
assemble_name (asm_out_file, name);
fputc ('\n', asm_out_file);
}
+#endif
+}
+
+/* Likewise for java classes to register. */
+
+void
+assemble_jcr (name)
+ const char *name;
+{
+#ifdef ASM_OUTPUT_JCR
+ ASM_OUTPUT_JCR (asm_out_file, name);
+#else
+ abort ();
#endif
}
Index: gcc/config/elfos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/elfos.h,v
retrieving revision 1.31
diff -p -u -r1.31 elfos.h
--- elfos.h 2001/07/13 23:33:37 1.31
+++ elfos.h 2001/07/30 04:59:43
@@ -380,6 +380,21 @@ dtors_section () \
while (0)
/* A C statement (sans semicolon) to output an
+ element in the table of java classes to register. */
+#define ASM_OUTPUT_JCR(FILE, NAME) \
+ do \
+ { \
+ jcr_section (); \
+ fprintf (FILE, "%s", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } \
+ while (0)
+
+/* The string to switch to the .jcr section for ELF objects. */
+#define JCR_SECTION_ASM_OP "\t.section\t.jcr,\"a\",@progbits"
+
+/* A C statement (sans semicolon) to output an
element in the table of global constructors. */
#define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME) \
do \
Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.100
diff -p -u -r1.100 class.c
--- class.c 2001/06/27 20:38:20 1.100
+++ class.c 2001/07/30 04:59:44
@@ -1861,12 +1860,22 @@ register_class ()
end = current;
}
-/* Generate a function that gets called at start-up (static contructor) time,
- which calls registerClass for all the compiled classes. */
+/* Emit something to register classes at start-up time.
+ The preferred mechanism is through the .jcr section, which contain
+ a list of pointers to classes which get registered during
+ constructor invoction time. The fallback mechanism is to generate
+ a `constructor' function which calls _Jv_RegisterClass for each
+ class in this file. */
+
void
emit_register_classes ()
{
+#ifdef JCR_SECTION
+ tree t;
+ for ( t = registered_class; t; t = TREE_CHAIN (t))
+ assemble_jcr (XEXP (XEXP (DECL_RTL (t), 0), 0));
+#else
extern tree get_file_function_name PARAMS ((int));
tree init_name = get_file_function_name ('I');
tree init_type = build_function_type (void_type_node, end_params_node);
@@ -1900,6 +1909,7 @@ emit_register_classes ()
}
current_function_decl = NULL_TREE;
assemble_constructor (IDENTIFIER_POINTER (init_name));
+#endif
}
void