Commit 21cd906e by Mark Mitchell Committed by Mark Mitchell

emit-rtl.c (free_emit_status): Take decl as a parameter.

	* emit-rtl.c (free_emit_status): Take decl as a parameter.
	(init_emit_once): Add more GC roots.
	* except.c (mark_func_eh_entry): New function.
	(mark_eh_node): Mark false_label and rethrow_label.
	(init_eh): Add more GC roots.
	* function.c (free_after_compilation): Take decl as a paramter.
	Call free_stmt_status.
	(mark_function_state): Don't assume x_parm_reg_stack_loc is
	non-NULL.
	* function.h (free_after_compilation): Change prototype.
	(free_varasm_status): Likewise.
	(free_emit_status): Likewise.
	(free_stmt_status): New function.
	* ggc-simple.c (rtx, vecs, trees, strings, bytes_alloced_since_gc):
	Remove, replacing with ...
	(ggc_status): New structure.
	(ggc_chain): New variable.
	(init_gcc): Define.
	(ggc_push_context): New function.
	(ggc_pop_context): Likewise.
	(ggc_alloc_rtx): Adjust for use of ggc_chain.
	(ggc_alloc_rtvec): Likewise.
	(ggc_alloc_tree): Likewise.
	(ggc_alloc_string): Likewise.
	(ggc_mark_rtx): Mark NOTE_SOURCE_FILE and NOTE_RANGE_INFO.
	(ggc_mark_tree): Give language-dependent code a chance to mark
	`x' nodes.
	(ggc_mark_tree_varray): Handle empty arrays.
	(ggc_collect): Adjust for use of ggc_chain.  Clear
	bytes_alloced_since_last_gc.
	* ggc.h (ggc_pop_context): New function.
	(ggc_push_context): Likewise.
	* print-tree.c (print_node): Don't print obstacks when GC'ing.
	* stmt.c (free_stmt_status): New function.
	(init_stmt_for_function): Clear last_expr_value.
	* toplev.c (rest_of_compilation): Always call free_after_compilation.
	Conditionalize call to ggc_collect.
	(main): Call init_ggc.
	* tree.c (push_obstacks): Do the push, even when GC'ing.
	(push_obstacks_nochange): Likewise.
	(pop_obstacks): Liekwise.
	* varasm.c (free_varasm_status): Take decl as a parameter.

From-SVN: r29170
parent 498ffa68
Tue Sep 7 00:47:52 1999 Mark Mitchell <mark@codesourcery.com>
* emit-rtl.c (free_emit_status): Take decl as a parameter.
(init_emit_once): Add more GC roots.
* except.c (mark_func_eh_entry): New function.
(mark_eh_node): Mark false_label and rethrow_label.
(init_eh): Add more GC roots.
* function.c (free_after_compilation): Take decl as a paramter.
Call free_stmt_status.
(mark_function_state): Don't assume x_parm_reg_stack_loc is
non-NULL.
* function.h (free_after_compilation): Change prototype.
(free_varasm_status): Likewise.
(free_emit_status): Likewise.
(free_stmt_status): New function.
* ggc-simple.c (rtx, vecs, trees, strings, bytes_alloced_since_gc):
Remove, replacing with ...
(ggc_status): New structure.
(ggc_chain): New variable.
(init_gcc): Define.
(ggc_push_context): New function.
(ggc_pop_context): Likewise.
(ggc_alloc_rtx): Adjust for use of ggc_chain.
(ggc_alloc_rtvec): Likewise.
(ggc_alloc_tree): Likewise.
(ggc_alloc_string): Likewise.
(ggc_mark_rtx): Mark NOTE_SOURCE_FILE and NOTE_RANGE_INFO.
(ggc_mark_tree): Give language-dependent code a chance to mark
`x' nodes.
(ggc_mark_tree_varray): Handle empty arrays.
(ggc_collect): Adjust for use of ggc_chain. Clear
bytes_alloced_since_last_gc.
* ggc.h (ggc_pop_context): New function.
(ggc_push_context): Likewise.
* print-tree.c (print_node): Don't print obstacks when GC'ing.
* stmt.c (free_stmt_status): New function.
(init_stmt_for_function): Clear last_expr_value.
* toplev.c (rest_of_compilation): Always call free_after_compilation.
Conditionalize call to ggc_collect.
(main): Call init_ggc.
* tree.c (push_obstacks): Do the push, even when GC'ing.
(push_obstacks_nochange): Likewise.
(pop_obstacks): Liekwise.
* varasm.c (free_varasm_status): Take decl as a parameter.
Tue Sep 7 08:15:49 1999 Gavin Romig-Koch <gavin@cygnus.com> Tue Sep 7 08:15:49 1999 Gavin Romig-Koch <gavin@cygnus.com>
* config/mips/mips.h (MULTILIB_ENDIAN_DEFAULT) : New macro. * config/mips/mips.h (MULTILIB_ENDIAN_DEFAULT) : New macro.
...@@ -155,7 +200,6 @@ Mon Sep 6 14:30:13 1999 Bernd Schmidt <bernds@cygnus.co.uk> ...@@ -155,7 +200,6 @@ Mon Sep 6 14:30:13 1999 Bernd Schmidt <bernds@cygnus.co.uk>
(ix86_mark_machine_status): New function. (ix86_mark_machine_status): New function.
(override_options): Set mark_machine_status. (override_options): Set mark_machine_status.
>>>>>>> 1.4290
Mon Sep 6 15:26:23 1999 Bernd Schmidt <bernds@cygnus.co.uk> Mon Sep 6 15:26:23 1999 Bernd Schmidt <bernds@cygnus.co.uk>
* tree.c (copy_node): Copy node contents also if doing GC. * tree.c (copy_node): Copy node contents also if doing GC.
...@@ -166,7 +210,6 @@ Mon Sep 6 08:42:06 1999 Alexandre Oliva <oliva@dcc.unicamp.br> ...@@ -166,7 +210,6 @@ Mon Sep 6 08:42:06 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
Mon Sep 6 02:42:36 1999 Jeffrey A Law (law@cygnus.com) Mon Sep 6 02:42:36 1999 Jeffrey A Law (law@cygnus.com)
>>>>>>> 1.4287
* collect2.c (scan_libraries): Fix thinko. * collect2.c (scan_libraries): Fix thinko.
* cse.c (delete_trivially_dead_insns): Do not skip the last * cse.c (delete_trivially_dead_insns): Do not skip the last
......
...@@ -1607,13 +1607,19 @@ restore_emit_status (p) ...@@ -1607,13 +1607,19 @@ restore_emit_status (p)
clear_emit_caches (); clear_emit_caches ();
} }
/* Clear out all parts of our state in F that can safely be discarded /* Clear out all parts of the state in F that can safely be discarded
after the function has been compiled, to let garbage collection after the function has been compiled, to let garbage collection
reclaim the memory. */ reclaim the memory. D is the declaration for the function just
compiled. Its output may have been deferred. */
void void
free_emit_status (f) free_emit_status (f, d)
struct function *f; struct function *f;
tree d;
{ {
if (DECL_DEFER_OUTPUT (d))
return;
free (f->emit->x_regno_reg_rtx); free (f->emit->x_regno_reg_rtx);
free (f->emit->regno_pointer_flag); free (f->emit->regno_pointer_flag);
free (f->emit->regno_pointer_align); free (f->emit->regno_pointer_align);
...@@ -3693,6 +3699,7 @@ init_emit_once (line_numbers) ...@@ -3693,6 +3699,7 @@ init_emit_once (line_numbers)
ggc_add_rtx_root (&const_tiny_rtx[0][0], sizeof(const_tiny_rtx)/sizeof(rtx)); ggc_add_rtx_root (&const_tiny_rtx[0][0], sizeof(const_tiny_rtx)/sizeof(rtx));
ggc_add_rtx_root (&const_true_rtx, 1);
ggc_add_rtx_root (&pic_offset_table_rtx, 1); ggc_add_rtx_root (&pic_offset_table_rtx, 1);
ggc_add_rtx_root (&struct_value_rtx, 1); ggc_add_rtx_root (&struct_value_rtx, 1);
ggc_add_rtx_root (&struct_value_incoming_rtx, 1); ggc_add_rtx_root (&struct_value_incoming_rtx, 1);
......
...@@ -472,6 +472,7 @@ static void mark_eh_node PROTO((struct eh_node *)); ...@@ -472,6 +472,7 @@ static void mark_eh_node PROTO((struct eh_node *));
static void mark_eh_stack PROTO((struct eh_stack *)); static void mark_eh_stack PROTO((struct eh_stack *));
static void mark_eh_queue PROTO((struct eh_queue *)); static void mark_eh_queue PROTO((struct eh_queue *));
static void mark_tree_label_node PROTO ((struct label_node *)); static void mark_tree_label_node PROTO ((struct label_node *));
static void mark_func_eh_entry PROTO ((void *));
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx)); rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
...@@ -2347,6 +2348,8 @@ mark_eh_node (node) ...@@ -2347,6 +2348,8 @@ mark_eh_node (node)
ggc_mark_rtx (node->entry->outer_context); ggc_mark_rtx (node->entry->outer_context);
ggc_mark_rtx (node->entry->exception_handler_label); ggc_mark_rtx (node->entry->exception_handler_label);
ggc_mark_tree (node->entry->finalization); ggc_mark_tree (node->entry->finalization);
ggc_mark_rtx (node->entry->false_label);
ggc_mark_rtx (node->entry->rethrow_label);
} }
node = node ->chain; node = node ->chain;
} }
...@@ -2405,6 +2408,33 @@ mark_eh_state (eh) ...@@ -2405,6 +2408,33 @@ mark_eh_state (eh)
ggc_mark_rtx (eh->x_eh_return_stub_label); ggc_mark_rtx (eh->x_eh_return_stub_label);
} }
/* Mark ARG (which is really a struct func_eh_entry**) for GC. */
static void
mark_func_eh_entry (arg)
void *arg;
{
struct func_eh_entry *fee;
struct handler_info *h;
int i;
fee = *((struct func_eh_entry **) arg);
for (i = 0; i < current_func_eh_entry; ++i)
{
ggc_mark_rtx (fee->rethrow_label);
for (h = fee->handlers; h; h = h->next)
{
ggc_mark_rtx (h->handler_label);
if (h->type_info != CATCH_ALL_TYPE)
ggc_mark_tree ((tree) h->type_info);
}
/* Skip to the next entry in the array. */
++fee;
}
}
/* This group of functions initializes the exception handling data /* This group of functions initializes the exception handling data
structures at the start of the compilation, initializes the data structures at the start of the compilation, initializes the data
structures at the start of a function, and saves and restores the structures at the start of a function, and saves and restores the
...@@ -2419,8 +2449,18 @@ init_eh () ...@@ -2419,8 +2449,18 @@ init_eh ()
first_rethrow_symbol = create_rethrow_ref (0); first_rethrow_symbol = create_rethrow_ref (0);
final_rethrow = gen_exception_label (); final_rethrow = gen_exception_label ();
last_rethrow_symbol = create_rethrow_ref (CODE_LABEL_NUMBER (final_rethrow)); last_rethrow_symbol = create_rethrow_ref (CODE_LABEL_NUMBER (final_rethrow));
}
ggc_add_rtx_root (&exception_handler_labels, 1);
ggc_add_rtx_root (&eh_return_context, 1);
ggc_add_rtx_root (&eh_return_stack_adjust, 1);
ggc_add_rtx_root (&eh_return_handler, 1);
ggc_add_rtx_root (&first_rethrow_symbol, 1);
ggc_add_rtx_root (&final_rethrow, 1);
ggc_add_rtx_root (&last_rethrow_symbol, 1);
ggc_add_root (&function_eh_regions, 1, sizeof (function_eh_regions),
mark_func_eh_entry);
}
/* Initialize the per-function EH information. */ /* Initialize the per-function EH information. */
void void
......
...@@ -390,17 +390,23 @@ pop_function_context () ...@@ -390,17 +390,23 @@ pop_function_context ()
/* Clear out all parts of the state in F that can safely be discarded /* Clear out all parts of the state in F that can safely be discarded
after the function has been compiled, to let garbage collection after the function has been compiled, to let garbage collection
reclaim the memory. */ reclaim the memory. D is the declaration for the function just
compiled. Its output may have been deferred. */
void void
free_after_compilation (f) free_after_compilation (f, d)
struct function *f; struct function *f;
tree d;
{ {
free_emit_status (f); free_emit_status (f, d);
free_varasm_status (f); free_varasm_status (f, d);
free_stmt_status (f, d);
free (f->x_parm_reg_stack_loc);
f->can_garbage_collect = 1; if (!DECL_DEFER_OUTPUT (d))
{
free (f->x_parm_reg_stack_loc);
f->can_garbage_collect = 1;
}
} }
/* Allocate fixed slots in the stack frame of the current function. */ /* Allocate fixed slots in the stack frame of the current function. */
...@@ -6682,9 +6688,10 @@ mark_function_state (p) ...@@ -6682,9 +6688,10 @@ mark_function_state (p)
ggc_mark_rtx (p->arg_offset_rtx); ggc_mark_rtx (p->arg_offset_rtx);
for (i = p->x_max_parm_reg, r = p->x_parm_reg_stack_loc; if (p->x_parm_reg_stack_loc)
i > 0; --i, ++r) for (i = p->x_max_parm_reg, r = p->x_parm_reg_stack_loc;
ggc_mark_rtx (*r); i > 0; --i, ++r)
ggc_mark_rtx (*r);
ggc_mark_rtx (p->return_rtx); ggc_mark_rtx (p->return_rtx);
ggc_mark_rtx (p->x_cleanup_label); ggc_mark_rtx (p->x_cleanup_label);
......
...@@ -549,11 +549,16 @@ extern void (*restore_lang_status) PROTO((struct function *)); ...@@ -549,11 +549,16 @@ extern void (*restore_lang_status) PROTO((struct function *));
extern void save_tree_status PROTO((struct function *)); extern void save_tree_status PROTO((struct function *));
extern void restore_tree_status PROTO((struct function *)); extern void restore_tree_status PROTO((struct function *));
extern void restore_emit_status PROTO((struct function *)); extern void restore_emit_status PROTO((struct function *));
extern void free_after_compilation PROTO((struct function *)); extern void free_after_compilation PROTO((struct function *,
tree));
extern void init_varasm_status PROTO((struct function *)); extern void init_varasm_status PROTO((struct function *));
extern void free_varasm_status PROTO((struct function *)); extern void free_varasm_status PROTO((struct function *,
extern void free_emit_status PROTO((struct function *)); tree));
extern void free_emit_status PROTO((struct function *,
tree));
extern void free_stmt_status PROTO((struct function *,
tree));
extern rtx get_first_block_beg PROTO((void)); extern rtx get_first_block_beg PROTO((void));
extern void init_virtual_regs PROTO((struct emit_status *)); extern void init_virtual_regs PROTO((struct emit_status *));
......
...@@ -50,24 +50,18 @@ struct ggc_rtx ...@@ -50,24 +50,18 @@ struct ggc_rtx
struct rtx_def rtx; struct rtx_def rtx;
}; };
static struct ggc_rtx *rtxs;
struct ggc_rtvec struct ggc_rtvec
{ {
struct ggc_rtvec *chain; struct ggc_rtvec *chain;
struct rtvec_def vec; struct rtvec_def vec;
}; };
static struct ggc_rtvec *vecs;
struct ggc_tree struct ggc_tree
{ {
struct ggc_tree *chain; struct ggc_tree *chain;
union tree_node tree; union tree_node tree;
}; };
static struct ggc_tree *trees;
struct ggc_string struct ggc_string
{ {
struct ggc_string *chain; struct ggc_string *chain;
...@@ -77,7 +71,19 @@ struct ggc_string ...@@ -77,7 +71,19 @@ struct ggc_string
#define GGC_STRING_MAGIC ((unsigned int)0xa1b2c3d4) #define GGC_STRING_MAGIC ((unsigned int)0xa1b2c3d4)
static struct ggc_string *strings; struct ggc_status
{
struct ggc_status *next;
struct ggc_rtx *rtxs;
struct ggc_rtvec *vecs;
struct ggc_tree *trees;
struct ggc_string *strings;
size_t bytes_alloced_since_gc;
};
/* A chain of GGC contexts. The currently active context is at the
front of the chain. */
static struct ggc_status *ggc_chain;
/* Some statistics. */ /* Some statistics. */
...@@ -85,7 +91,6 @@ static int n_rtxs_collected; ...@@ -85,7 +91,6 @@ static int n_rtxs_collected;
static int n_vecs_collected; static int n_vecs_collected;
static int n_trees_collected; static int n_trees_collected;
static int n_strings_collected; static int n_strings_collected;
static int bytes_alloced_since_gc;
extern int gc_time; extern int gc_time;
#ifdef GGC_DUMP #ifdef GGC_DUMP
...@@ -103,6 +108,81 @@ static void ggc_mark_tree_hash_table_ptr PROTO ((void *elt)); ...@@ -103,6 +108,81 @@ static void ggc_mark_tree_hash_table_ptr PROTO ((void *elt));
static boolean ggc_mark_tree_hash_table_entry PROTO ((struct hash_entry *, static boolean ggc_mark_tree_hash_table_entry PROTO ((struct hash_entry *,
hash_table_key)); hash_table_key));
/* Called once to initialize the garbage collector. */
void
init_ggc PROTO ((void))
{
/* Initialize the global context. */
ggc_push_context ();
}
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
void
ggc_push_context PROTO ((void))
{
struct ggc_status *gs = (struct ggc_status *) xmalloc (sizeof (*gs));
bzero (gs, sizeof (*gs));
gs->next = ggc_chain;
ggc_chain = gs;
}
/* Finish a GC context. Any uncollected memory in the new context
will be merged with the old context. */
void
ggc_pop_context PROTO ((void))
{
struct ggc_rtx *r;
struct ggc_rtvec *v;
struct ggc_tree *t;
struct ggc_string *s;
struct ggc_status *gs;
gs = ggc_chain;
r = gs->rtxs;
if (r)
{
while (r->chain)
r = r->chain;
r->chain = gs->next->rtxs;
gs->next->rtxs = gs->rtxs;
}
v = gs->vecs;
if (v)
{
while (v->chain)
v = v->chain;
v->chain = gs->next->vecs;
gs->next->vecs = gs->vecs;
}
t = gs->trees;
if (t)
{
while (t->chain)
t = t->chain;
t->chain = gs->next->trees;
gs->next->trees = gs->trees;
}
s = gs->strings;
if (s)
{
while (s->chain)
s = s->chain;
s->chain = gs->next->strings;
gs->next->strings = gs->strings;
}
ggc_chain = gs->next;
free (gs);
}
/* These allocators are dreadfully simple, with no caching whatsoever so /* These allocators are dreadfully simple, with no caching whatsoever so
that Purify-like tools that do allocation versioning can catch errors. that Purify-like tools that do allocation versioning can catch errors.
This collector is never going to go fast anyway. */ This collector is never going to go fast anyway. */
...@@ -116,14 +196,14 @@ ggc_alloc_rtx (nslots) ...@@ -116,14 +196,14 @@ ggc_alloc_rtx (nslots)
n = (struct ggc_rtx *) xmalloc (size); n = (struct ggc_rtx *) xmalloc (size);
bzero ((char *) n, size); bzero ((char *) n, size);
n->chain = rtxs; n->chain = ggc_chain->rtxs;
rtxs = n; ggc_chain->rtxs = n;
#ifdef GGC_DUMP #ifdef GGC_DUMP
fprintf (dump, "alloc rtx %p\n", &n->rtx); fprintf (dump, "alloc rtx %p\n", &n->rtx);
#endif #endif
bytes_alloced_since_gc += size; ggc_chain->bytes_alloced_since_gc += size;
return &n->rtx; return &n->rtx;
} }
...@@ -137,14 +217,14 @@ ggc_alloc_rtvec (nelt) ...@@ -137,14 +217,14 @@ ggc_alloc_rtvec (nelt)
v = (struct ggc_rtvec *) xmalloc (size); v = (struct ggc_rtvec *) xmalloc (size);
bzero ((char *) v, size); bzero ((char *) v, size);
v->chain = vecs; v->chain = ggc_chain->vecs;
vecs = v; ggc_chain->vecs = v;
#ifdef GGC_DUMP #ifdef GGC_DUMP
fprintf(dump, "alloc vec %p\n", &v->vec); fprintf(dump, "alloc vec %p\n", &v->vec);
#endif #endif
bytes_alloced_since_gc += size; ggc_chain->bytes_alloced_since_gc += size;
return &v->vec; return &v->vec;
} }
...@@ -158,14 +238,14 @@ ggc_alloc_tree (length) ...@@ -158,14 +238,14 @@ ggc_alloc_tree (length)
n = (struct ggc_tree *) xmalloc (size); n = (struct ggc_tree *) xmalloc (size);
bzero ((char *) n, size); bzero ((char *) n, size);
n->chain = trees; n->chain = ggc_chain->trees;
trees = n; ggc_chain->trees = n;
#ifdef GGC_DUMP #ifdef GGC_DUMP
fprintf(dump, "alloc tree %p\n", &n->tree); fprintf(dump, "alloc tree %p\n", &n->tree);
#endif #endif
bytes_alloced_since_gc += size; ggc_chain->bytes_alloced_since_gc += size;
return &n->tree; return &n->tree;
} }
...@@ -187,18 +267,18 @@ ggc_alloc_string (contents, length) ...@@ -187,18 +267,18 @@ ggc_alloc_string (contents, length)
size = (s->string - (char *)s) + length + 1; size = (s->string - (char *)s) + length + 1;
s = (struct ggc_string *) xmalloc(size); s = (struct ggc_string *) xmalloc(size);
s->chain = strings; s->chain = ggc_chain->strings;
s->magic_mark = GGC_STRING_MAGIC; s->magic_mark = GGC_STRING_MAGIC;
if (contents) if (contents)
bcopy (contents, s->string, length); bcopy (contents, s->string, length);
s->string[length] = 0; s->string[length] = 0;
strings = s; ggc_chain->strings = s;
#ifdef GGC_DUMP #ifdef GGC_DUMP
fprintf(dump, "alloc string %p\n", &s->string); fprintf(dump, "alloc string %p\n", &s->string);
#endif #endif
bytes_alloced_since_gc += size; ggc_chain->bytes_alloced_since_gc += size;
return s->string; return s->string;
} }
...@@ -313,6 +393,21 @@ ggc_mark_rtx (r) ...@@ -313,6 +393,21 @@ ggc_mark_rtx (r)
case CONST_DOUBLE: case CONST_DOUBLE:
ggc_mark_rtx (CONST_DOUBLE_CHAIN (r)); ggc_mark_rtx (CONST_DOUBLE_CHAIN (r));
break; break;
case NOTE:
switch (NOTE_LINE_NUMBER (r))
{
case NOTE_INSN_RANGE_START:
case NOTE_INSN_RANGE_END:
case NOTE_INSN_LIVE:
ggc_mark_rtx (NOTE_RANGE_INFO (r));
break;
default:
if (NOTE_LINE_NUMBER (r) >= 0)
ggc_mark_string (NOTE_SOURCE_FILE (r));
break;
}
break;
default: default:
break; break;
...@@ -475,6 +570,10 @@ ggc_mark_tree (t) ...@@ -475,6 +570,10 @@ ggc_mark_tree (t)
ggc_mark_tree (TREE_OPERAND (t, i)); ggc_mark_tree (TREE_OPERAND (t, i));
break; break;
} }
case 'x':
lang_mark_tree (t);
break;
} }
} }
...@@ -486,8 +585,9 @@ ggc_mark_tree_varray (v) ...@@ -486,8 +585,9 @@ ggc_mark_tree_varray (v)
{ {
int i; int i;
for (i = v->num_elements - 1; i >= 0; --i) if (v)
ggc_mark_tree (VARRAY_TREE (v, i)); for (i = v->num_elements - 1; i >= 0; --i)
ggc_mark_tree (VARRAY_TREE (v, i));
} }
/* Mark the hash table-entry HE. It's key field is really a tree. */ /* Mark the hash table-entry HE. It's key field is really a tree. */
...@@ -534,11 +634,12 @@ ggc_collect () ...@@ -534,11 +634,12 @@ ggc_collect ()
struct ggc_tree *t, **tp; struct ggc_tree *t, **tp;
struct ggc_string *s, **sp; struct ggc_string *s, **sp;
struct ggc_root *x; struct ggc_root *x;
struct ggc_status *gs;
int time, n_rtxs, n_trees, n_vecs, n_strings; int time, n_rtxs, n_trees, n_vecs, n_strings;
#ifndef ENABLE_CHECKING #ifndef ENABLE_CHECKING
/* See if it's even worth our while. */ /* See if it's even worth our while. */
if (bytes_alloced_since_gc < 64*1024) if (ggc_chain->bytes_alloced_since_gc < 64*1024)
return; return;
#endif #endif
...@@ -548,14 +649,17 @@ ggc_collect () ...@@ -548,14 +649,17 @@ ggc_collect ()
time = get_run_time (); time = get_run_time ();
/* Clean out all of the GC marks. */ /* Clean out all of the GC marks. */
for (r = rtxs; r != NULL; r = r->chain) for (gs = ggc_chain; gs; gs = gs->next)
r->rtx.gc_mark = 0; {
for (v = vecs; v != NULL; v = v->chain) for (r = gs->rtxs; r != NULL; r = r->chain)
v->vec.gc_mark = 0; r->rtx.gc_mark = 0;
for (t = trees; t != NULL; t = t->chain) for (v = gs->vecs; v != NULL; v = v->chain)
t->tree.common.gc_mark = 0; v->vec.gc_mark = 0;
for (s = strings; s != NULL; s = s->chain) for (t = gs->trees; t != NULL; t = t->chain)
s->magic_mark = GGC_STRING_MAGIC; t->tree.common.gc_mark = 0;
for (s = gs->strings; s != NULL; s = s->chain)
s->magic_mark = GGC_STRING_MAGIC;
}
/* Mark through all the roots. */ /* Mark through all the roots. */
for (x = roots; x != NULL; x = x->next) for (x = roots; x != NULL; x = x->next)
...@@ -570,7 +674,9 @@ ggc_collect () ...@@ -570,7 +674,9 @@ ggc_collect ()
} }
/* Sweep the resulting dead nodes. */ /* Sweep the resulting dead nodes. */
rp = &rtxs, r = rtxs, n_rtxs = 0; rp = &ggc_chain->rtxs;
r = ggc_chain->rtxs;
n_rtxs = 0;
while (r != NULL) while (r != NULL)
{ {
struct ggc_rtx *chain = r->chain; struct ggc_rtx *chain = r->chain;
...@@ -587,7 +693,9 @@ ggc_collect () ...@@ -587,7 +693,9 @@ ggc_collect ()
*rp = NULL; *rp = NULL;
n_rtxs_collected += n_rtxs; n_rtxs_collected += n_rtxs;
vp = &vecs, v = vecs, n_vecs = 0; vp = &ggc_chain->vecs;
v = ggc_chain->vecs;
n_vecs = 0;
while (v != NULL) while (v != NULL)
{ {
struct ggc_rtvec *chain = v->chain; struct ggc_rtvec *chain = v->chain;
...@@ -604,7 +712,9 @@ ggc_collect () ...@@ -604,7 +712,9 @@ ggc_collect ()
*vp = NULL; *vp = NULL;
n_vecs_collected += n_vecs; n_vecs_collected += n_vecs;
tp = &trees, t = trees, n_trees = 0; tp = &ggc_chain->trees;
t = ggc_chain->trees;
n_trees = 0;
while (t != NULL) while (t != NULL)
{ {
struct ggc_tree *chain = t->chain; struct ggc_tree *chain = t->chain;
...@@ -621,7 +731,9 @@ ggc_collect () ...@@ -621,7 +731,9 @@ ggc_collect ()
*tp = NULL; *tp = NULL;
n_trees_collected += n_trees; n_trees_collected += n_trees;
sp = &strings, s = strings, n_strings = 0; sp = &ggc_chain->strings;
s = ggc_chain->strings;
n_strings = 0;
while (s != NULL) while (s != NULL)
{ {
struct ggc_string *chain = s->chain; struct ggc_string *chain = s->chain;
...@@ -637,8 +749,10 @@ ggc_collect () ...@@ -637,8 +749,10 @@ ggc_collect ()
} }
*sp = NULL; *sp = NULL;
n_strings_collected += n_strings; n_strings_collected += n_strings;
ggc_chain->bytes_alloced_since_gc = 0;
gc_time += time = get_run_time () - time; time = get_run_time () - time;
gc_time += time;
if (!quiet_flag) if (!quiet_flag)
{ {
......
...@@ -43,6 +43,13 @@ struct hash_table; ...@@ -43,6 +43,13 @@ struct hash_table;
extern void init_ggc PROTO ((void)); extern void init_ggc PROTO ((void));
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
extern void ggc_pop_context PROTO ((void));
/* Finish a GC context. Any uncollected memory in the new context
will be merged with the old context. */
extern void ggc_push_context PROTO ((void));
/* Allocation. */ /* Allocation. */
struct rtx_def *ggc_alloc_rtx PROTO ((int nslots)); struct rtx_def *ggc_alloc_rtx PROTO ((int nslots));
......
...@@ -270,7 +270,8 @@ print_node (file, prefix, node, indent) ...@@ -270,7 +270,8 @@ print_node (file, prefix, node, indent)
if (TREE_TYPE (node)) if (TREE_TYPE (node))
indent_to (file, indent + 3); indent_to (file, indent + 3);
print_obstack_name ((char *) node, file, ""); if (!ggc_p)
print_obstack_name ((char *) node, file, "");
indent_to (file, indent + 3); indent_to (file, indent + 3);
} }
......
...@@ -550,6 +550,22 @@ mark_goto_fixup (g) ...@@ -550,6 +550,22 @@ mark_goto_fixup (g)
} }
} }
/* Clear out all parts of the state in F that can safely be discarded
after the function has been compiled, to let garbage collection
reclaim the memory. D is the declaration for the function just
compiled. Its output may have been deferred. */
void
free_stmt_status (f, d)
struct function *f;
tree d ATTRIBUTE_UNUSED;
{
/* We're about to free the function obstack. If we hold pointers to
things allocated there, then we'll try to mark them when we do
GC. So, we clear them out here explicitly. */
f->stmt->x_goto_fixup_chain = 0;
}
/* Mark P for GC. */ /* Mark P for GC. */
void void
...@@ -602,6 +618,7 @@ init_stmt_for_function () ...@@ -602,6 +618,7 @@ init_stmt_for_function ()
/* We are not processing a ({...}) grouping. */ /* We are not processing a ({...}) grouping. */
expr_stmts_for_value = 0; expr_stmts_for_value = 0;
last_expr_type = 0; last_expr_type = 0;
last_expr_value = NULL_RTX;
init_eh_for_function (); init_eh_for_function ();
} }
......
...@@ -4466,13 +4466,13 @@ rest_of_compilation (decl) ...@@ -4466,13 +4466,13 @@ rest_of_compilation (decl)
init_recog_no_volatile (); init_recog_no_volatile ();
/* We're done with this function. */ /* We're done with this function. Free up memory if we can. */
if (! DECL_DEFER_OUTPUT (decl)) free_after_compilation (current_function, decl);
free_after_compilation (current_function);
current_function = 0; current_function = 0;
ggc_collect (); if (ggc_p)
ggc_collect ();
/* The parsing time is all the time spent in yyparse /* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */ *except* what is spent in this function. */
...@@ -4793,6 +4793,9 @@ main (argc, argv) ...@@ -4793,6 +4793,9 @@ main (argc, argv)
flag_short_enums = DEFAULT_SHORT_ENUMS; flag_short_enums = DEFAULT_SHORT_ENUMS;
#endif #endif
/* Initialize the garbage-collector. */
if (ggc_p)
init_ggc ();
ggc_add_root (&input_file_stack, 1, sizeof input_file_stack, ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
&mark_file_stack); &mark_file_stack);
......
...@@ -476,9 +476,6 @@ push_obstacks (current, saveable) ...@@ -476,9 +476,6 @@ push_obstacks (current, saveable)
{ {
struct obstack_stack *p; struct obstack_stack *p;
if (ggc_p)
return;
p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack, p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
(sizeof (struct obstack_stack))); (sizeof (struct obstack_stack)));
...@@ -501,9 +498,6 @@ push_obstacks_nochange () ...@@ -501,9 +498,6 @@ push_obstacks_nochange ()
{ {
struct obstack_stack *p; struct obstack_stack *p;
if (ggc_p)
return;
p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack, p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
(sizeof (struct obstack_stack))); (sizeof (struct obstack_stack)));
...@@ -522,9 +516,6 @@ pop_obstacks () ...@@ -522,9 +516,6 @@ pop_obstacks ()
{ {
struct obstack_stack *p; struct obstack_stack *p;
if (ggc_p)
return;
p = obstack_stack; p = obstack_stack;
obstack_stack = p->next; obstack_stack = p->next;
......
...@@ -3210,13 +3210,22 @@ mark_varasm_state (p) ...@@ -3210,13 +3210,22 @@ mark_varasm_state (p)
ggc_mark_rtx (p->x_const_double_chain); ggc_mark_rtx (p->x_const_double_chain);
} }
/* Clear out all parts of our state in F that can safely be discarded /* Clear out all parts of the state in F that can safely be discarded
after the function has been compiled. */ after the function has been compiled, to let garbage collection
reclaim the memory. D is the declaration for the function just
compiled. Its output may have been deferred. */
void void
free_varasm_status (f) free_varasm_status (f, d)
struct function *f; struct function *f;
tree d;
{ {
struct varasm_status *p = f->varasm; struct varasm_status *p;
if (DECL_DEFER_OUTPUT (d))
return;
p = f->varasm;
free (p->x_const_rtx_hash_table); free (p->x_const_rtx_hash_table);
free (p->x_const_rtx_sym_hash_table); free (p->x_const_rtx_sym_hash_table);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment