This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: *ping* [PATCH] unit-at-a-time for java
- From: Jeff Sturm <jsturm at one-point dot com>
- To: Andrew Haley <aph at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 3 Sep 2003 02:16:30 -0400 (EDT)
- Subject: Re: *ping* [PATCH] unit-at-a-time for java
On Fri, 1 Aug 2003, Andrew Haley wrote:
> Jeff Sturm writes:
> > Richard has already approved the cgraphunit hunks.
> >
> > http://gcc.gnu.org/ml/gcc-patches/2003-07/msg02158.html
>
> This is OK if you have no libgcj testsuite regressions at -O3.
I've taken another look at this. The present state of libgcj on mainline
is that it doesn't build with GCJFLAGS="-O3 -g" and has one testsuite
failure at -O3.
The following patch (together with
http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00082.html) corrects both and
enables unit-at-a-time for gcj. It avoids the problem I reported earlier
(ICE in dwarf2out.c) by defining a start_inlining hook that cancels
inlining if the function is not yet expanded.
Tested on i686-pc-linux-gnu. OK for mainline?
Jeff
2003-09-03 Jeff Sturm <jsturm@one-point.com>
* decl.c (java_expand_body): New function.
* expr.c (build_class_init): Set DECL_IGNORED_P.
* java-tree.h (start_complete_expand_method,
java_expand_body): Declare.
* jcf-parse.c (cgraph.h): Include.
(java_parse_file): Handle flag_unit_at_a_time.
* lang.c (LANG_HOOKS_TREE_INLINING_START_INLINING,
LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION): Define.
(java_estimate_num_insns): Use walk_tree_without_duplicates.
(java_start_inlining): New function.
* parse.h (java_finish_classes): Declare.
* parse.y: Include cgraph.h.
(block): Don't special-case empty block production.
(craft_constructor): Set DECL_INLINE.
(source_end_java_method): Handle flag_unit_at_a_time.
Replace inline code with call to java_expand_body.
(start_complete_expand_method): Remove static modifier.
(java_expand_method_bodies): Patch function tree for
class initialization and/or synchronization as needed.
Don't begin RTL expansion yet.
(java_expand_classes): Check flag_unit_at_a_time before
calling finish_class.
(java_finish_classes): New function.
(java_complete_lhs): Ensure COMPOUND_EXPR has non-NULL type.
(patch_assignment): Set DECL_CONTEXT on temporary variable.
(emit_test_initialization): Set DECL_IGNORED_P.
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.159
diff -u -p -r1.159 decl.c
--- decl.c 4 Aug 2003 19:06:24 -0000 1.159
+++ decl.c 3 Sep 2003 05:43:39 -0000
@@ -1811,6 +1811,59 @@ end_java_method (void)
current_function_decl = NULL_TREE;
}
+/* Expand a function's body. */
+
+void
+java_expand_body (tree fndecl)
+{
+ const char *saved_input_filename = input_filename;
+ int saved_lineno = input_line;
+
+ current_function_decl = fndecl;
+ input_filename = DECL_SOURCE_FILE (fndecl);
+ input_line = DECL_SOURCE_LINE (fndecl);
+
+ timevar_push (TV_EXPAND);
+
+ /* Prepare the function for tree completion. */
+ start_complete_expand_method (fndecl);
+
+ if (! flag_emit_class_files && ! flag_emit_xref)
+ {
+ /* Initialize the RTL code for the function. */
+ init_function_start (fndecl);
+
+ /* Set up parameters and prepare for return, for the function. */
+ expand_function_start (fndecl, 0);
+
+ /* Generate the RTL for this function. */
+ expand_expr_stmt_value (DECL_SAVED_TREE (fndecl), 0, 1);
+ }
+
+ /* Pop out of its parameters. */
+ pushdecl_force_head (DECL_ARGUMENTS (fndecl));
+ poplevel (1, 0, 1);
+ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+ if (! flag_emit_class_files && ! flag_emit_xref)
+ {
+ /* Generate RTL for function exit. */
+ input_line = DECL_FUNCTION_LAST_LINE (fndecl);
+ expand_function_end ();
+
+ /* Run the optimizers and output the assembler code
+ for this function. */
+ rest_of_compilation (fndecl);
+ }
+
+ timevar_pop (TV_EXPAND);
+
+ input_filename = saved_input_filename;
+ input_line = saved_lineno;
+
+ current_function_decl = NULL_TREE;
+}
+
/* Dump FUNCTION_DECL FN as tree dump PHASE. */
static void
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.169
diff -u -p -r1.169 expr.c
--- expr.c 25 Jul 2003 10:27:43 -0000 1.169
+++ expr.c 3 Sep 2003 05:43:40 -0000
@@ -1710,6 +1710,8 @@ build_class_init (tree clas, tree expr)
optimizing class initialization. */
if (!STATIC_CLASS_INIT_OPT_P ())
DECL_BIT_INDEX(*init_test_decl) = -1;
+ /* Don't emit any symbolic debugging info for this decl. */
+ DECL_IGNORED_P (*init_test_decl) = 1;
}
init = build (CALL_EXPR, void_type_node,
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.182
diff -u -p -r1.182 java-tree.h
--- java-tree.h 12 Aug 2003 20:34:50 -0000 1.182
+++ java-tree.h 3 Sep 2003 05:43:41 -0000
@@ -1297,6 +1297,9 @@ extern void compile_resource_file (const
extern void write_resource_constructor (void);
extern void init_resource_processing (void);
+extern void start_complete_expand_method (tree);
+extern void java_expand_body (tree);
+
#define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
@@ -1750,4 +1753,5 @@ enum
};
#undef DEBUG_JAVA_BINDING_LEVELS
+
#endif /* ! GCC_JAVA_TREE_H */
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.142
diff -u -p -r1.142 jcf-parse.c
--- jcf-parse.c 28 Jun 2003 00:30:31 -0000 1.142
+++ jcf-parse.c 3 Sep 2003 05:43:41 -0000
@@ -42,6 +42,7 @@ The Free Software Foundation is independ
#include "debug.h"
#include "assert.h"
#include "tm_p.h"
+#include "cgraph.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
@@ -1119,6 +1120,13 @@ java_parse_file (int set_yydebug ATTRIBU
java_expand_classes ();
if (!java_report_errors () && !flag_syntax_only)
{
+ if (flag_unit_at_a_time)
+ {
+ cgraph_finalize_compilation_unit ();
+ cgraph_optimize ();
+ java_finish_classes ();
+ }
+
emit_register_classes ();
if (flag_indirect_dispatch)
emit_offset_symbol_table ();
Index: lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.141
diff -u -p -r1.141 lang.c
--- lang.c 17 Jul 2003 13:25:21 -0000 1.141
+++ lang.c 3 Sep 2003 05:43:42 -0000
@@ -67,6 +67,7 @@ static bool java_dump_tree (void *, tree
static void dump_compound_expr (dump_info_p, tree);
static bool java_decl_ok_for_sibcall (tree);
static int java_estimate_num_insns (tree);
+static int java_start_inlining (tree);
#ifndef TARGET_OBJECT_SUFFIX
# define TARGET_OBJECT_SUFFIX ".o"
@@ -253,12 +254,18 @@ struct language_function GTY(())
#undef LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS
#define LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS java_estimate_num_insns
+#undef LANG_HOOKS_TREE_INLINING_START_INLINING
+#define LANG_HOOKS_TREE_INLINING_START_INLINING java_start_inlining
+
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree
#undef LANG_HOOKS_DECL_OK_FOR_SIBCALL
#define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall
+#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
+#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body
+
/* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -1178,8 +1185,21 @@ static int
java_estimate_num_insns (tree decl)
{
int num = 0;
- walk_tree (&DECL_SAVED_TREE (decl), java_estimate_num_insns_1, &num, NULL);
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (decl),
+ java_estimate_num_insns_1, &num);
return num;
+}
+
+/* Start inlining fn. Called by the tree inliner via
+ lang_hooks.tree_inlining.cannot_inline_tree_fn. */
+
+static int
+java_start_inlining (tree fn)
+{
+ /* A java function's body doesn't have a BLOCK structure suitable
+ for debug output until it is expanded. Prevent inlining functions
+ that are not yet expanded. */
+ return TREE_ASM_WRITTEN (fn) ? 1 : 0;
}
#include "gt-java-lang.h"
Index: parse.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.h,v
retrieving revision 1.91
diff -u -p -r1.91 parse.h
--- parse.h 9 Jun 2003 12:57:15 -0000 1.91
+++ parse.h 3 Sep 2003 05:43:42 -0000
@@ -941,6 +941,7 @@ ATTRIBUTE_NORETURN
#endif
;
extern void java_expand_classes (void);
+extern void java_finish_classes (void);
extern GTY(()) struct parser_ctxt *ctxp;
extern GTY(()) struct parser_ctxt *ctxp_for_generation;
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.439
diff -u -p -r1.439 parse.y
--- parse.y 12 Aug 2003 20:34:51 -0000 1.439
+++ parse.y 3 Sep 2003 05:43:47 -0000
@@ -71,6 +71,7 @@ definitions and other extensions. */
#include "ggc.h"
#include "debug.h"
#include "tree-inline.h"
+#include "cgraph.h"
/* Local function prototypes */
static char *java_accstring_lookup (int);
@@ -141,7 +142,6 @@ static tree java_complete_tree (tree);
static tree maybe_generate_pre_expand_clinit (tree);
static int analyze_clinit_body (tree, tree);
static int maybe_yank_clinit (tree);
-static void start_complete_expand_method (tree);
static void java_complete_expand_method (tree);
static void java_expand_method_bodies (tree);
static int unresolved_type_p (tree, tree *);
@@ -1352,14 +1352,8 @@ variable_initializers:
/* 19.11 Production from 14: Blocks and Statements */
block:
- OCB_TK CCB_TK
- {
- /* Store the location of the `}' when doing xrefs */
- if (current_function_decl && flag_emit_xref)
- DECL_END_SOURCE_LINE (current_function_decl) =
- EXPR_WFL_ADD_COL ($2.location, 1);
- $$ = empty_stmt_node;
- }
+ block_begin block_end
+ { $$ = $2; }
| block_begin block_statements block_end
{ $$ = $3; }
;
@@ -5405,6 +5399,7 @@ craft_constructor (tree class_decl, tree
/* Now, mark the artificial parameters. */
DECL_FUNCTION_NAP (decl) = artificial;
DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
+ DECL_INLINE (decl) = 1;
return decl;
}
@@ -7476,30 +7471,20 @@ source_end_java_method (void)
patched. Dump it to a file if the user requested it. */
dump_java_tree (TDI_original, fndecl);
- java_optimize_inline (fndecl);
-
- /* Generate function's code */
- if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
- && ! flag_emit_class_files
- && ! flag_emit_xref)
- expand_expr_stmt (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)));
-
- /* pop out of its parameters */
- pushdecl_force_head (DECL_ARGUMENTS (fndecl));
- poplevel (1, 0, 1);
- BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
-
- /* Generate rtl for function exit. */
- if (! flag_emit_class_files && ! flag_emit_xref)
+ /* In unit-at-a-time mode, don't expand the method yet. */
+ if (DECL_SAVED_TREE (fndecl) && flag_unit_at_a_time)
{
- input_line = DECL_FUNCTION_LAST_LINE (fndecl);
- expand_function_end ();
-
- /* Run the optimizers and output assembler code for this function. */
- rest_of_compilation (fndecl);
+ cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+ current_function_decl = NULL_TREE;
+ java_parser_context_restore_global ();
+ return;
}
- current_function_decl = NULL_TREE;
+ java_optimize_inline (fndecl);
+
+ /* Expand the function's body. */
+ java_expand_body (fndecl);
+
java_parser_context_restore_global ();
}
@@ -7969,7 +7954,7 @@ maybe_yank_clinit (tree mdecl)
/* Install the argument from MDECL. Suitable to completion and
expansion of mdecl's body. */
-static void
+void
start_complete_expand_method (tree mdecl)
{
tree tem;
@@ -8112,15 +8097,26 @@ java_expand_method_bodies (tree class)
tree decl;
for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl))
{
- if (!DECL_FUNCTION_BODY (decl))
+ tree block;
+ tree body;
+
+ if (! DECL_FUNCTION_BODY (decl))
continue;
current_function_decl = decl;
- /* Save the function for inlining. */
- if (flag_inline_trees)
- DECL_SAVED_TREE (decl) =
- BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
+ block = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
+
+ if (TREE_CODE (block) != BLOCK)
+ abort ();
+
+ /* Save the function body for inlining. */
+ DECL_SAVED_TREE (decl) = block;
+
+ body = BLOCK_EXPR_BODY (block);
+
+ if (TREE_TYPE (body) == NULL_TREE)
+ abort ();
/* It's time to assign the variable flagging static class
initialization based on which classes invoked static methods
@@ -8153,15 +8149,41 @@ java_expand_method_bodies (tree class)
}
}
- /* Prepare the function for RTL expansion */
- start_complete_expand_method (decl);
+ /* Prepend class initialization to static methods. */
+ if (METHOD_STATIC (decl) && ! METHOD_PRIVATE (decl)
+ && ! flag_emit_class_files
+ && ! DECL_CLINIT_P (decl)
+ && ! CLASS_INTERFACE (TYPE_NAME (class)))
+ {
+ tree init = build (CALL_EXPR, void_type_node,
+ build_address_of (soft_initclass_node),
+ build_tree_list (NULL_TREE,
+ build_class_ref (class)),
+ NULL_TREE);
+ TREE_SIDE_EFFECTS (init) = 1;
+ body = build (COMPOUND_EXPR, TREE_TYPE (body), init, body);
+ BLOCK_EXPR_BODY (block) = body;
+ }
+
+ /* Wrap synchronized method bodies in a monitorenter
+ plus monitorexit cleanup. */
+ if (METHOD_SYNCHRONIZED (decl) && ! flag_emit_class_files)
+ {
+ tree enter, exit, lock;
+ if (METHOD_STATIC (decl))
+ lock = build_class_ref (class);
+ else
+ lock = DECL_ARGUMENTS (decl);
+ BUILD_MONITOR_ENTER (enter, lock);
+ BUILD_MONITOR_EXIT (exit, lock);
- /* Expand function start, generate initialization flag
- assignment, and handle synchronized methods. */
- complete_start_java_method (decl);
+ body = build (COMPOUND_EXPR, void_type_node,
+ enter,
+ build (TRY_FINALLY_EXPR, void_type_node, body, exit));
+ BLOCK_EXPR_BODY (block) = body;
+ }
- /* Expand the rest of the function body and terminate
- expansion. */
+ /* Expand the the function body. */
source_end_java_method ();
}
}
@@ -9124,12 +9146,30 @@ java_expand_classes (void)
else if (! flag_syntax_only)
{
java_expand_method_bodies (current_class);
- finish_class ();
+ if (!flag_unit_at_a_time)
+ finish_class ();
}
}
}
}
+void
+java_finish_classes (void)
+{
+ static struct parser_ctxt *cur_ctxp = NULL;
+ for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
+ {
+ tree current;
+ ctxp = cur_ctxp;
+ for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
+ {
+ current_class = TREE_TYPE (current);
+ outgoing_cpool = TYPE_CPOOL (current_class);
+ finish_class ();
+ }
+ }
+}
+
/* Wrap non WFL PRIMARY around a WFL and set EXPR_WFL_QUALIFICATION to
a tree list node containing RIGHT. Fore coming RIGHTs will be
chained to this hook. LOCATION contains the location of the
@@ -11659,6 +11699,8 @@ java_complete_lhs (tree node)
&& TREE_CODE (wfl_op2) != DEFAULT_EXPR)
unreachable_stmt_error (*ptr);
}
+ if (TREE_TYPE (*ptr) == NULL_TREE)
+ TREE_TYPE (*ptr) = void_type_node;
ptr = next;
}
*ptr = java_complete_tree (*ptr);
@@ -12889,6 +12931,7 @@ patch_assignment (tree node, tree wfl_op
tree block = build (BLOCK, TREE_TYPE (new_rhs), NULL);
tree assignment
= build (MODIFY_EXPR, TREE_TYPE (new_rhs), tmp, fold (new_rhs));
+ DECL_CONTEXT (tmp) = current_function_decl;
BLOCK_VARS (block) = tmp;
BLOCK_EXPR_BODY (block)
= build (COMPOUND_EXPR, TREE_TYPE (new_rhs), assignment, tmp);
@@ -16221,6 +16264,8 @@ emit_test_initialization (void **entry_p
LOCAL_CLASS_INITIALIZATION_FLAG (decl) = 1;
DECL_CONTEXT (decl) = current_function_decl;
DECL_INITIAL (decl) = boolean_true_node;
+ /* Don't emit any symbolic debugging info for this decl. */
+ DECL_IGNORED_P (decl) = 1;
/* The trick is to find the right context for it. */
block = BLOCK_SUBBLOCKS (GET_CURRENT_BLOCK (current_function_decl));