tree.c (restore_tree_status): Also free up temporary storage when we finish a toplevel function.
* tree.c (restore_tree_status): Also free up temporary storage when we finish a toplevel function. (dump_tree_statistics): Print stats for backend obstacks. * libgcc2.c (__throw): Don't copy the return address. * dwarf2out.c (expand_builtin_dwarf_reg_size): Ignore return address. * except.c (exceptions_via_longjmp): Initialize to 2 (uninitialized). * toplev.c (main): Initialize exceptions_via_longjmp. * tree.c: Add extra_inline_obstacks. (save_tree_status): Use it. (restore_tree_status): If this is a toplevel inline obstack and we didn't want to save anything on it, recycle it. (print_inline_obstack_statistics): New fn. * function.c (pop_function_context_from): Pass context to restore_tree_status. * obstack.h (obstack_empty_p): New macro. From-SVN: r16050
This commit is contained in:
parent
6bd35f8671
commit
d1485032c8
8 changed files with 143 additions and 25 deletions
|
@ -1,7 +1,30 @@
|
|||
Sat Oct 18 13:47:15 1997 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* tree.c (restore_tree_status): Also free up temporary storage
|
||||
when we finish a toplevel function.
|
||||
(dump_tree_statistics): Print stats for backend obstacks.
|
||||
|
||||
Sat Oct 18 12:47:31 1997 Doug Evans <dje@canuck.cygnus.com>
|
||||
|
||||
* expr.c (use_group_regs): Don't call use_reg for MEMs.
|
||||
|
||||
Sat Oct 18 09:49:46 1997 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* libgcc2.c (__throw): Don't copy the return address.
|
||||
* dwarf2out.c (expand_builtin_dwarf_reg_size): Ignore return address.
|
||||
|
||||
* except.c (exceptions_via_longjmp): Initialize to 2 (uninitialized).
|
||||
* toplev.c (main): Initialize exceptions_via_longjmp.
|
||||
|
||||
* tree.c: Add extra_inline_obstacks.
|
||||
(save_tree_status): Use it.
|
||||
(restore_tree_status): If this is a toplevel inline obstack and we
|
||||
didn't want to save anything on it, recycle it.
|
||||
(print_inline_obstack_statistics): New fn.
|
||||
* function.c (pop_function_context_from): Pass context to
|
||||
restore_tree_status.
|
||||
* obstack.h (obstack_empty_p): New macro.
|
||||
|
||||
Sat Oct 18 00:43:59 1997 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* i386/freebsd.h (ASM_COMMENT_START): Fix.
|
||||
|
|
|
@ -520,27 +520,31 @@ expand_builtin_dwarf_reg_size (reg_tree, target)
|
|||
tree reg_tree;
|
||||
rtx target;
|
||||
{
|
||||
int i, n_ranges, size;
|
||||
int size;
|
||||
struct reg_size_range ranges[5];
|
||||
tree t, t2;
|
||||
|
||||
ranges[0].beg = 0;
|
||||
ranges[0].size = GET_MODE_SIZE (reg_raw_mode[0]);
|
||||
n_ranges = 1;
|
||||
int i = 0;
|
||||
int n_ranges = 0;
|
||||
int last_size = -1;
|
||||
|
||||
for (i = 1; i < FIRST_PSEUDO_REGISTER; ++i)
|
||||
for (; i < FIRST_PSEUDO_REGISTER; ++i)
|
||||
{
|
||||
/* The return address is out of order on the MIPS, and we don't use
|
||||
copy_reg for it anyway, so we don't care here how large it is. */
|
||||
if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
|
||||
continue;
|
||||
|
||||
size = GET_MODE_SIZE (reg_raw_mode[i]);
|
||||
if (size != ranges[n_ranges-1].size)
|
||||
if (size != last_size)
|
||||
{
|
||||
ranges[n_ranges-1].end = i-1;
|
||||
ranges[n_ranges].beg = i;
|
||||
ranges[n_ranges].size = GET_MODE_SIZE (reg_raw_mode[i]);
|
||||
ranges[n_ranges].size = last_size = GET_MODE_SIZE (reg_raw_mode[i]);
|
||||
++n_ranges;
|
||||
assert (n_ranges < 5);
|
||||
}
|
||||
ranges[n_ranges-1].end = i;
|
||||
}
|
||||
ranges[n_ranges-1].end = i-1;
|
||||
|
||||
/* The usual case: fp regs surrounded by general regs. */
|
||||
if (n_ranges == 3 && ranges[0].size == ranges[2].size)
|
||||
|
|
|
@ -98,7 +98,7 @@ Boston, MA 02111-1307, USA. */
|
|||
is stored in a section named .eh_frame and the information for the
|
||||
entire shared object or program is registered with a call to
|
||||
__register_frame. On other targets, the information for each
|
||||
translation unit is registered separately with a static constructor.
|
||||
translation unit is registered from the file generated by collect2.
|
||||
__register_frame is defined in frame.c, and is responsible for
|
||||
recording all of the unwind regions into one list (which is kept in a
|
||||
static variable named unwind_table_list).
|
||||
|
@ -409,11 +409,7 @@ Boston, MA 02111-1307, USA. */
|
|||
/* One to use setjmp/longjmp method of generating code for exception
|
||||
handling. */
|
||||
|
||||
#if DWARF2_UNWIND_INFO
|
||||
int exceptions_via_longjmp = 0;
|
||||
#else
|
||||
int exceptions_via_longjmp = 1;
|
||||
#endif
|
||||
int exceptions_via_longjmp = 2;
|
||||
|
||||
/* One to enable asynchronous exception support. */
|
||||
|
||||
|
|
|
@ -610,7 +610,7 @@ pop_function_context_from (context)
|
|||
reg_renumber = 0;
|
||||
current_function_args_info = p->args_info;
|
||||
|
||||
restore_tree_status (p);
|
||||
restore_tree_status (p, context);
|
||||
restore_storage_status (p);
|
||||
restore_expr_status (p);
|
||||
restore_emit_status (p);
|
||||
|
|
|
@ -3733,7 +3733,7 @@ label:
|
|||
sub_udata = p;
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
|
||||
if (udata->saved[i])
|
||||
if (i != udata->retaddr_column && udata->saved[i])
|
||||
{
|
||||
#ifdef INCOMING_REGNO
|
||||
/* If you modify the saved value of the return address
|
||||
|
|
|
@ -332,6 +332,11 @@ int obstack_chunk_size (struct obstack *obstack);
|
|||
({ struct obstack *__o = (OBSTACK); \
|
||||
(unsigned) (__o->chunk_limit - __o->next_free); })
|
||||
|
||||
#define obstack_empty_p(OBSTACK) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
(__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
|
||||
|
||||
#define obstack_grow(OBSTACK,where,length) \
|
||||
__extension__ \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
|
@ -460,6 +465,9 @@ __extension__ \
|
|||
#define obstack_room(h) \
|
||||
(unsigned) ((h)->chunk_limit - (h)->next_free)
|
||||
|
||||
#define obstack_empty_p(h) \
|
||||
((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
|
||||
|
||||
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
|
||||
so that we can avoid having void expressions
|
||||
in the arms of the conditional expression.
|
||||
|
|
|
@ -4294,6 +4294,15 @@ main (argc, argv, envp)
|
|||
OVERRIDE_OPTIONS;
|
||||
#endif
|
||||
|
||||
if (exceptions_via_longjmp == 2)
|
||||
{
|
||||
#ifdef DWARF2_UNWIND_INFO
|
||||
exceptions_via_longjmp = ! DWARF2_UNWIND_INFO;
|
||||
#else
|
||||
exceptions_via_longjmp = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (profile_block_flag == 3)
|
||||
{
|
||||
warning ("`-ax' and `-a' are conflicting options. `-a' ignored.");
|
||||
|
|
94
gcc/tree.c
94
gcc/tree.c
|
@ -81,6 +81,10 @@ struct obstack maybepermanent_obstack;
|
|||
|
||||
struct simple_obstack_stack *toplev_inline_obstacks;
|
||||
|
||||
/* Former elements of toplev_inline_obstacks that have been recycled. */
|
||||
|
||||
struct simple_obstack_stack *extra_inline_obstacks;
|
||||
|
||||
/* This is a list of function_maybepermanent_obstacks for inline functions
|
||||
nested in the current function that were compiled in the middle of
|
||||
compiling other functions. */
|
||||
|
@ -381,12 +385,22 @@ save_tree_status (p, context)
|
|||
head = &f->inline_obstacks;
|
||||
}
|
||||
|
||||
current = ((struct simple_obstack_stack *)
|
||||
xmalloc (sizeof (struct simple_obstack_stack)));
|
||||
if (context == NULL_TREE && extra_inline_obstacks)
|
||||
{
|
||||
current = extra_inline_obstacks;
|
||||
extra_inline_obstacks = current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = ((struct simple_obstack_stack *)
|
||||
xmalloc (sizeof (struct simple_obstack_stack)));
|
||||
|
||||
current->obstack
|
||||
= (struct obstack *) xmalloc (sizeof (struct obstack));
|
||||
gcc_obstack_init (current->obstack);
|
||||
}
|
||||
|
||||
current->obstack = (struct obstack *) xmalloc (sizeof (struct obstack));
|
||||
function_maybepermanent_obstack = current->obstack;
|
||||
gcc_obstack_init (function_maybepermanent_obstack);
|
||||
|
||||
current->next = *head;
|
||||
*head = current;
|
||||
|
@ -411,8 +425,9 @@ save_tree_status (p, context)
|
|||
This is used after a nested function. */
|
||||
|
||||
void
|
||||
restore_tree_status (p)
|
||||
restore_tree_status (p, context)
|
||||
struct function *p;
|
||||
tree context;
|
||||
{
|
||||
all_types_permanent = p->all_types_permanent;
|
||||
momentary_stack = p->momentary_stack;
|
||||
|
@ -428,6 +443,29 @@ restore_tree_status (p)
|
|||
past the nested function's end. */
|
||||
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
|
||||
|
||||
/* If we were compiling a toplevel function, we can free this space now. */
|
||||
if (context == NULL_TREE)
|
||||
{
|
||||
obstack_free (&temporary_obstack, temporary_firstobj);
|
||||
obstack_free (&momentary_obstack, momentary_function_firstobj);
|
||||
}
|
||||
|
||||
/* If we were compiling a toplevel function that we don't actually want
|
||||
to save anything from, return the obstack to the pool. */
|
||||
if (context == NULL_TREE
|
||||
&& obstack_empty_p (function_maybepermanent_obstack))
|
||||
{
|
||||
struct simple_obstack_stack *current, **p = &toplev_inline_obstacks;
|
||||
|
||||
while ((*p)->obstack != function_maybepermanent_obstack)
|
||||
p = &((*p)->next);
|
||||
current = *p;
|
||||
*p = current->next;
|
||||
|
||||
current->next = extra_inline_obstacks;
|
||||
extra_inline_obstacks = current;
|
||||
}
|
||||
|
||||
obstack_free (function_obstack, 0);
|
||||
free (function_obstack);
|
||||
|
||||
|
@ -4469,24 +4507,58 @@ decl_type_context (decl)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Print debugging information about the size of the
|
||||
toplev_inline_obstacks. */
|
||||
|
||||
void
|
||||
print_inline_obstack_statistics ()
|
||||
{
|
||||
struct simple_obstack_stack *current = toplev_inline_obstacks;
|
||||
int n_obstacks = 0;
|
||||
unsigned long n_alloc = 0;
|
||||
int n_chunks = 0;
|
||||
|
||||
for (; current; current = current->next, ++n_obstacks)
|
||||
{
|
||||
struct obstack *o = current->obstack;
|
||||
struct _obstack_chunk *chunk = o->chunk;
|
||||
|
||||
n_alloc += o->next_free - chunk->contents;
|
||||
chunk = chunk->prev;
|
||||
++n_chunks;
|
||||
for (; chunk; chunk = chunk->prev, ++n_chunks)
|
||||
n_alloc += chunk->limit - &chunk->contents[0];
|
||||
}
|
||||
fprintf (stderr, "inline obstacks: %d obstacks, %lu bytes, %d chunks\n",
|
||||
n_obstacks, n_alloc, n_chunks);
|
||||
}
|
||||
|
||||
/* Print debugging information about the obstack O, named STR. */
|
||||
|
||||
void
|
||||
print_obstack_statistics (str, o)
|
||||
char *str;
|
||||
struct obstack *o;
|
||||
{
|
||||
struct _obstack_chunk *chunk = o->chunk;
|
||||
int n_chunks = 0;
|
||||
int n_alloc = 0;
|
||||
int n_chunks = 1;
|
||||
unsigned long n_alloc = 0;
|
||||
|
||||
n_alloc += o->next_free - chunk->contents;
|
||||
chunk = chunk->prev;
|
||||
while (chunk)
|
||||
{
|
||||
n_chunks += 1;
|
||||
n_alloc += chunk->limit - &chunk->contents[0];
|
||||
chunk = chunk->prev;
|
||||
}
|
||||
fprintf (stderr, "obstack %s: %d bytes, %d chunks\n",
|
||||
fprintf (stderr, "obstack %s: %lu bytes, %d chunks\n",
|
||||
str, n_alloc, n_chunks);
|
||||
}
|
||||
|
||||
/* Print debugging information about tree nodes generated during the compile,
|
||||
and any language-specific information. */
|
||||
|
||||
void
|
||||
dump_tree_statistics ()
|
||||
{
|
||||
|
@ -4512,6 +4584,12 @@ dump_tree_statistics ()
|
|||
#else
|
||||
fprintf (stderr, "(No per-node statistics)\n");
|
||||
#endif
|
||||
print_obstack_statistics ("permanent_obstack", &permanent_obstack);
|
||||
print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
|
||||
print_obstack_statistics ("temporary_obstack", &temporary_obstack);
|
||||
print_obstack_statistics ("momentary_obstack", &momentary_obstack);
|
||||
print_obstack_statistics ("temp_decl_obstack", &temp_decl_obstack);
|
||||
print_inline_obstack_statistics ();
|
||||
print_lang_statistics ();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue