OSDN Git Service

* tree.c (restore_tree_status): Also free up temporary storage
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 18 Oct 1997 21:10:32 +0000 (21:10 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 18 Oct 1997 21:10:32 +0000 (21:10 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@16050 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/dwarf2out.c
gcc/except.c
gcc/function.c
gcc/libgcc2.c
gcc/obstack.h
gcc/toplev.c
gcc/tree.c

index 2f848a6..6cc2374 100644 (file)
@@ -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.
index 7a49fd4..eebac52 100644 (file)
@@ -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)
index 6f3de66..2a2554b 100644 (file)
@@ -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.  */
 
index 644cc72..61a72fe 100644 (file)
@@ -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);
index 78834df..ae97c53 100644 (file)
@@ -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
index dd8e861..1b172ac 100644 (file)
@@ -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.
index 225964b..41e2c5b 100644 (file)
@@ -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.");
index 6812aa4..d5eabae 100644 (file)
@@ -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 ();
 }
 \f