This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[incremental] Patch: FYI: fork server before back end
- From: Tom Tromey <tromey at redhat dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 06 Sep 2007 16:44:55 -0600
- Subject: [incremental] Patch: FYI: fork server before back end
- Reply-to: Tom Tromey <tromey at redhat dot com>
I'm checking this in on the incremental-compiler branch.
This changes the server to fork after parsing a file. The child
process compiles as usual while the parent waits for it. This is
something of a hack to avoid having to look into running the back end
multiple times. At some later point I may give this a real try. I
suspect at the very least the long-term code generation plan will
require adding a new model to cgraph.
The resulting server still crashes if you feed it two real files. I
think that at least the front end needs to have separate notions of
"initialize once" and "initialize per compilation".
Tom
ChangeLog:
2007-09-06 Tom Tromey <tromey@redhat.com>
* server.h (server_start_back_end): Declare.
* server.c (server_start_back_end): New function.
* cgraph.h (cgraph_unit_reset, cgraph_reset): Declare.
* cgraphunit.c (cgraph_unit_reset): New function.
* cgraph.c (cgraph_reset): New function.
* toplev.c (server_callback): Garbage collect. Reset cgraph
modules.
(server_mode): New global.
(toplev_main): Set it.
(compile_file): Call server_start_back_end.
(do_compile): Only initialize front end once.
Index: cgraph.c
===================================================================
--- cgraph.c (revision 127650)
+++ cgraph.c (working copy)
@@ -131,6 +131,24 @@
them, to support -fno-toplevel-reorder. */
int cgraph_order;
+void
+cgraph_reset (void)
+{
+ cgraph_hash = NULL;
+ cgraph_nodes = NULL;
+ cgraph_nodes_queue = NULL;
+ cgraph_new_nodes = NULL;
+ cgraph_n_nodes = 0;
+ cgraph_max_uid = 0;
+ cgraph_max_pid = 0;
+ cgraph_global_info_ready = false;
+ cgraph_state = CGRAPH_STATE_CONSTRUCTION;
+ cgraph_function_flags_ready = false;
+ cgraph_asm_nodes = NULL;
+ cgraph_asm_last_node = NULL;
+ cgraph_order = 0;
+}
+
static hashval_t hash_node (const void *);
static int eq_node (const void *, const void *);
Index: cgraph.h
===================================================================
--- cgraph.h (revision 127650)
+++ cgraph.h (working copy)
@@ -287,6 +287,7 @@
extern GTY(()) int cgraph_order;
/* In cgraph.c */
+void cgraph_reset (void);
void dump_cgraph (FILE *);
void dump_cgraph_node (FILE *, struct cgraph_node *);
void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
@@ -324,6 +325,7 @@
void cgraph_add_new_function (tree, bool);
/* In cgraphunit.c */
+void cgraph_unit_reset (void);
void cgraph_finalize_function (tree, bool);
void cgraph_finalize_compilation_unit (void);
void cgraph_optimize (void);
Index: toplev.c
===================================================================
--- toplev.c (revision 128155)
+++ toplev.c (working copy)
@@ -119,6 +119,9 @@
/* True if we don't need a backend (e.g. preprocessing only). */
static bool no_backend;
+/* True if we're running as a server. */
+static bool server_mode;
+
/* Length of line when printing switch values. */
#define MAX_LINE 75
@@ -1056,10 +1059,16 @@
if (flag_syntax_only)
return;
+ if (server_mode && server_start_back_end ())
+ return;
+
lang_hooks.decls.final_write_globals ();
if (errorcount || sorrycount)
- return;
+ {
+ /* FIXME: server mode... */
+ return;
+ }
varpool_assemble_pending_decls ();
finish_aliases_2 ();
@@ -1114,6 +1123,14 @@
into the assembly file here, and hence we can not output anything to the
assembly file after this point. */
targetm.asm_out.file_end ();
+
+ /* FIXME: this is a bit lame, but our caller doesn't know if we
+ forked. */
+ if (server_mode)
+ {
+ finalize ();
+ exit (0);
+ }
}
/* Parse a -d... command line switch. */
@@ -2226,6 +2243,14 @@
pex_free (px);
}
+ /* Clean up after this compilation. FIXME: instead of clean_up()
+ running before a job, as we have in a couple files, we should
+ clean each module after compilation. This will reduce peak
+ memory use. */
+ cgraph_reset ();
+ cgraph_unit_reset ();
+ ggc_collect ();
+
/* Make sure to close dup'd stderr, so that client will terminate
properly. The server loop will take care of the fd we were
passed. */
@@ -2252,6 +2277,7 @@
/* Unit-at-a-time is needed to enable the C type-merging
machinery. */
flag_unit_at_a_time = 1;
+ server_mode = true;
server_main_loop (argv[0], fd);
return SUCCESS_EXIT_CODE;
}
Index: cgraphunit.c
===================================================================
--- cgraphunit.c (revision 127650)
+++ cgraphunit.c (working copy)
@@ -170,6 +170,13 @@
static GTY (()) tree static_ctors;
static GTY (()) tree static_dtors;
+void
+cgraph_unit_reset (void)
+{
+ static_ctors = NULL_TREE;
+ static_dtors = NULL_TREE;
+}
+
/* When target does not have ctors and dtors, we call all constructor
and destructor by special initialization/destruction function
recognized by collect2.
Index: server.c
===================================================================
--- server.c (revision 127995)
+++ server.c (working copy)
@@ -316,6 +316,33 @@
unlink (server_socket_name);
}
+/* Fork to let the back end do its work. Returns true in the parent,
+ false in the child. Will print a message and return true if there
+ is an error. The parent waits for the child to exit. */
+bool
+server_start_back_end (void)
+{
+ pid_t child;
+ int status;
+
+ child = fork ();
+ if (child == -1)
+ {
+ error ("fork of server failed: %s", xstrerror (errno));
+ return true;
+ }
+ else if (child == 0)
+ {
+ /* Child process. */
+ return false;
+ }
+
+ /* Parent. */
+ waitpid (child, &status, 0);
+ /* FIXME: handle STATUS somehow. */
+ return true;
+}
+
/* Make a connection to a running server. PROGNAME is the name of the
server to connect to. Returns true on success, false on
failure. */
Index: server.h
===================================================================
--- server.h (revision 127995)
+++ server.h (working copy)
@@ -23,6 +23,7 @@
/* Functions for the server to use. */
extern void server_start (char *);
extern void server_main_loop (const char *progname, int);
+extern bool server_start_back_end (void);
/* Functions for the client to use. */
extern bool client_connect (const char *);