Special-case tree_decl/tree_list allocations.
authorMark Mitchell <mark@codesourcery.com>
Thu, 4 Jan 2001 21:18:27 +0000 (21:18 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 4 Jan 2001 21:18:27 +0000 (21:18 +0000)
* ggc-page.c (OBJECT_PER_PAGE): Reimplement.
(OBJECT_SIZE): New macro.
(NUM_EXTRA_ORDER): Likewise.
(extra_order_size_table): New variable.
(NUM_ORDERS): New macro.
(objects_per_page_table): New variable.
(object_size_table): New variable.
(G.pages): Use NUM_ORDERS to bound the array.
(G.page_tails): Likewise.
(DIV_ROUND_UP): Remove.
(BITMAP_SIZE): Use CEIL, instead of DIV_ROUND_UP.
(alloc_page): Use OBJECT_SIZE.
(size_lookup): Don't make it const.
(ggc_alloc): Use OBJECT_SIZE.
(ggc_set_mark): Likewise.
(ggc_get_size): Likewise.
(init_ggc): Set up the object_size_table, objects_per_page_table,
and adjust size_lookup.
(ggc_recalculate_in_use_p): Use CEIL, not DIV_ROUND_UP.
(ggc_pop_context): Use NUM_ORDERS.
(clear_marks): Likewise.
(sweep_pages): Likewise.
(poison_pages): Likewise.
(ggc_print_statistics): Use OBJECT_SIZE.

From-SVN: r38692

gcc/ChangeLog
gcc/ggc-page.c

index d37423bc50c32af21118e34ac947c4948a92bb08..d422a7b06f1c0064aba55c558cd500b7fdad1788 100644 (file)
@@ -1,3 +1,31 @@
+2001-01-04  Mark Mitchell  <mark@codesourcery.com>
+
+       Special-case tree_decl/tree_list allocations.
+       * ggc-page.c (OBJECT_PER_PAGE): Reimplement.
+       (OBJECT_SIZE): New macro.
+       (NUM_EXTRA_ORDER): Likewise.
+       (extra_order_size_table): New variable.
+       (NUM_ORDERS): New macro.
+       (objects_per_page_table): New variable.
+       (object_size_table): New variable.
+       (G.pages): Use NUM_ORDERS to bound the array.
+       (G.page_tails): Likewise.
+       (DIV_ROUND_UP): Remove.
+       (BITMAP_SIZE): Use CEIL, instead of DIV_ROUND_UP.
+       (alloc_page): Use OBJECT_SIZE.
+       (size_lookup): Don't make it const.
+       (ggc_alloc): Use OBJECT_SIZE.
+       (ggc_set_mark): Likewise.
+       (ggc_get_size): Likewise.
+       (init_ggc): Set up the object_size_table, objects_per_page_table,
+       and adjust size_lookup.
+       (ggc_recalculate_in_use_p): Use CEIL, not DIV_ROUND_UP.
+       (ggc_pop_context): Use NUM_ORDERS.
+       (clear_marks): Likewise.
+       (sweep_pages): Likewise.
+       (poison_pages): Likewise.
+       (ggc_print_statistics): Use OBJECT_SIZE.
+
 Thu Jan  4 15:54:05 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * varasm.c (output_constructor): Use HOST_WIDE_INT for sizes.
index 2b64f45db53e88a6dc12df2427cf312013bdc67a..e4bf283498e364a0330e5ea1c0467a3c00803818 100644 (file)
@@ -1,5 +1,5 @@
 /* "Bag-of-pages" garbage collector for the GNU compiler.
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -133,6 +133,39 @@ Boston, MA 02111-1307, USA.  */
 #define LOOKUP_L2(p) \
   (((size_t) (p) >> G.lg_pagesize) & ((1 << PAGE_L2_BITS) - 1))
 
+/* The number of objects per allocation page, for objects on a page of
+   the indicated ORDER.  */
+#define OBJECTS_PER_PAGE(ORDER) objects_per_page_table[ORDER]
+
+/* The size of an object on a page of the indicated ORDER.  */
+#define OBJECT_SIZE(ORDER) object_size_table[ORDER]
+
+/* The number of extra orders, not corresponding to power-of-two sized
+   objects.  */
+
+#define NUM_EXTRA_ORDERS \
+  (sizeof (extra_order_size_table) / sizeof (extra_order_size_table[0]))
+
+/* The Ith entry is the maximum size of an object to be stored in the
+   Ith extra order.  Adding a new entry to this array is the *only*
+   thing you need to do to add a new special allocation size.  */
+
+static const size_t extra_order_size_table[] = {
+  sizeof (struct tree_decl),
+  sizeof (struct tree_list)
+};
+
+/* The total number of orders.  */
+
+#define NUM_ORDERS (HOST_BITS_PER_PTR + NUM_EXTRA_ORDERS)
+
+/* The Ith entry is the number of objects on a page or order I.  */
+
+static unsigned objects_per_page_table[NUM_ORDERS];
+
+/* The Ith entry is the size of an object on a page of order I.  */
+
+static size_t object_size_table[NUM_ORDERS];
 
 /* A page_entry records the status of an allocation page.  This
    structure is dynamically sized to fit the bitmap in_use_p.  */
@@ -199,12 +232,12 @@ static struct globals
      If there are any pages with free objects, they will be at the
      head of the list.  NULL if there are no page-entries for this
      object size.  */
-  page_entry *pages[HOST_BITS_PER_PTR];
+  page_entry *pages[NUM_ORDERS];
 
   /* The Nth element in this array is the last page with objects of
      size 2^N.  NULL if there are no page-entries for this object
      size.  */
-  page_entry *page_tails[HOST_BITS_PER_PTR];
+  page_entry *page_tails[NUM_ORDERS];
 
   /* Lookup table for associating allocation pages with object addresses.  */
   page_table lookup;
@@ -237,20 +270,10 @@ static struct globals
   FILE *debug_file;
 } G;
 
-
-/* Compute DIVIDEND / DIVISOR, rounded up.  */
-#define DIV_ROUND_UP(Dividend, Divisor) \
-  (((Dividend) + (Divisor) - 1) / (Divisor))
-
-/* The number of objects per allocation page, for objects of size
-   2^ORDER.  */
-#define OBJECTS_PER_PAGE(Order) \
-  ((Order) >= G.lg_pagesize ? 1 : G.pagesize / ((size_t)1 << (Order)))
-
 /* The size in bytes required to maintain a bitmap for the objects
    on a page-entry.  */
 #define BITMAP_SIZE(Num_objects) \
-  (DIV_ROUND_UP ((Num_objects), HOST_BITS_PER_LONG) * sizeof(long))
+  (CEIL ((Num_objects), HOST_BITS_PER_LONG) * sizeof(long))
 
 /* Skip garbage collection if the current allocation is not at least
    this factor times the allocation at the end of the last collection.
@@ -459,7 +482,7 @@ alloc_page (order)
   num_objects = OBJECTS_PER_PAGE (order);
   bitmap_size = BITMAP_SIZE (num_objects + 1);
   page_entry_size = sizeof (page_entry) - sizeof (long) + bitmap_size;
-  entry_size = num_objects * (1 << order);
+  entry_size = num_objects * OBJECT_SIZE (order);
 
   entry = NULL;
   page = NULL;
@@ -529,7 +552,7 @@ alloc_page (order)
   if (GGC_DEBUG_LEVEL >= 2)
     fprintf (G.debug_file, 
             "Allocating page at %p, object size=%d, data %p-%p\n",
-            (PTR) entry, 1 << order, page, page + entry_size - 1);
+            (PTR) entry, OBJECT_SIZE (order), page, page + entry_size - 1);
 
   return entry;
 }
@@ -603,7 +626,7 @@ release_pages ()
 /* This table provides a fast way to determine ceil(log_2(size)) for
    allocation requests.  The minimum allocation size is four bytes.  */
 
-static unsigned char const size_lookup[257] = 
+static unsigned char size_lookup[257] = 
 { 
   2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 
   4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
@@ -640,7 +663,7 @@ ggc_alloc (size)
   else
     {
       order = 9;
-      while (size > ((size_t) 1 << order))
+      while (size > OBJECT_SIZE (order))
        order++;
     }
 
@@ -695,7 +718,7 @@ ggc_alloc (size)
       /* Next time, try the next bit.  */
       entry->next_bit_hint = hint + 1;
 
-      object_offset = hint << order;
+      object_offset = hint * OBJECT_SIZE (order);
     }
 
   /* Set the in-use bit.  */
@@ -721,17 +744,17 @@ ggc_alloc (size)
 #ifdef GGC_POISON
   /* `Poison' the entire allocated object, including any padding at
      the end.  */
-  memset (result, 0xaf, 1 << order);
+  memset (result, 0xaf, OBJECT_SIZE (order));
 #endif
 
   /* Keep track of how many bytes are being allocated.  This
      information is used in deciding when to collect.  */
-  G.allocated += (size_t) 1 << order;
+  G.allocated += OBJECT_SIZE (order);
 
   if (GGC_DEBUG_LEVEL >= 3)
     fprintf (G.debug_file, 
             "Allocating object, requested size=%d, actual=%d at %p on %p\n",
-            (int) size, 1 << order, result, (PTR) entry);
+            (int) size, OBJECT_SIZE (order), result, (PTR) entry);
 
   return result;
 }
@@ -758,7 +781,7 @@ ggc_set_mark (p)
 
   /* Calculate the index of the object on the page; this is its bit
      position in the in_use_p bitmap.  */
-  bit = (((const char *) p) - entry->page) >> entry->order;
+  bit = (((const char *) p) - entry->page) / OBJECT_SIZE (entry->order);
   word = bit / HOST_BITS_PER_LONG;
   mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
   
@@ -793,7 +816,7 @@ ggc_get_size (p)
      const void *p;
 {
   page_entry *pe = lookup_page_table_entry (p);
-  return 1 << pe->order;
+  return OBJECT_SIZE (pe->order);
 }
 \f
 /* Initialize the ggc-mmap allocator.  */
@@ -801,6 +824,8 @@ ggc_get_size (p)
 void
 init_ggc ()
 {
+  unsigned order;
+
   G.pagesize = getpagesize();
   G.lg_pagesize = exact_log2 (G.pagesize);
 
@@ -837,6 +862,35 @@ init_ggc ()
     munmap (p, G.pagesize);
   }
 #endif
+
+  /* Initialize the object size table.  */
+  for (order = 0; order < HOST_BITS_PER_PTR; ++order)
+    object_size_table[order] = (size_t) 1 << order;
+  for (order = HOST_BITS_PER_PTR; order < NUM_ORDERS; ++order)
+    object_size_table[order] = 
+      extra_order_size_table[order - HOST_BITS_PER_PTR];
+
+  /* Initialize the objects-per-page table.  */
+  for (order = 0; order < NUM_ORDERS; ++order)
+    {
+      objects_per_page_table[order] = G.pagesize / OBJECT_SIZE (order);
+      if (objects_per_page_table[order] == 0)
+       objects_per_page_table[order] = 1;
+    }
+
+  /* Reset the size_lookup array to put appropriately sized objects in
+     the special orders.  All objects bigger than the previous power
+     of two, but no greater than the special size, should go in the
+     new order.  */
+  for (order = HOST_BITS_PER_PTR; order < NUM_ORDERS; ++order)
+    {
+      int o;
+      int i;
+
+      o = size_lookup[OBJECT_SIZE (order)];
+      for (i = OBJECT_SIZE (order); size_lookup [i] == o; --i)
+       size_lookup[i] = order;
+    }
 }
 
 /* Increment the `GC context'.  Objects allocated in an outer context
@@ -871,8 +925,8 @@ ggc_recalculate_in_use_p (p)
 
   /* Combine the IN_USE_P and SAVE_IN_USE_P arrays.  */
   for (i = 0; 
-       i < DIV_ROUND_UP (BITMAP_SIZE (num_objects),
-                        sizeof (*p->in_use_p));
+       i < CEIL (BITMAP_SIZE (num_objects),
+                sizeof (*p->in_use_p));
        ++i)
     {
       unsigned long j;
@@ -903,7 +957,7 @@ ggc_pop_context ()
   /* Any remaining pages in the popped context are lowered to the new
      current context; i.e. objects allocated in the popped context and
      left over are imported into the previous context.  */
-  for (order = 2; order < HOST_BITS_PER_PTR; order++)
+  for (order = 2; order < NUM_ORDERS; order++)
     {
       page_entry *p;
 
@@ -931,7 +985,7 @@ clear_marks ()
 {
   unsigned order;
 
-  for (order = 2; order < HOST_BITS_PER_PTR; order++)
+  for (order = 2; order < NUM_ORDERS; order++)
     {
       size_t num_objects = OBJECTS_PER_PAGE (order);
       size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
@@ -975,7 +1029,7 @@ sweep_pages ()
 {
   unsigned order;
 
-  for (order = 2; order < HOST_BITS_PER_PTR; order++)
+  for (order = 2; order < NUM_ORDERS; order++)
     {
       /* The last page-entry to consider, regardless of entries
         placed at the end of the list.  */
@@ -1002,7 +1056,7 @@ sweep_pages ()
              allocated memory.  */
          live_objects = num_objects - p->num_free_objects;
 
-         G.allocated += ((size_t) 1 << order) * live_objects;
+         G.allocated += OBJECT_SIZE (order) * live_objects;
 
          /* Only objects on pages in the topmost context should get
             collected.  */
@@ -1082,10 +1136,10 @@ poison_pages ()
 {
   unsigned order;
 
-  for (order = 2; order < HOST_BITS_PER_PTR; order++)
+  for (order = 2; order < NUM_ORDERS; order++)
     {
       size_t num_objects = OBJECTS_PER_PAGE (order);
-      size_t size = (size_t) 1 << order;
+      size_t size = OBJECT_SIZE (order);
       page_entry *p;
 
       for (p = G.pages[order]; p != NULL; p = p->next)
@@ -1188,7 +1242,7 @@ ggc_print_statistics ()
      allocation.  */
   fprintf (stderr, "\n%-5s %10s  %10s  %10s\n",
           "Log", "Allocated", "Used", "Overhead");
-  for (i = 0; i < HOST_BITS_PER_PTR; ++i)
+  for (i = 0; i < NUM_ORDERS; ++i)
     {
       page_entry *p;
       size_t allocated;
@@ -1208,7 +1262,7 @@ ggc_print_statistics ()
        {
          allocated += p->bytes;
          in_use += 
-           (OBJECTS_PER_PAGE (i) - p->num_free_objects) * (1 << i);
+           (OBJECTS_PER_PAGE (i) - p->num_free_objects) * OBJECT_SIZE (i);
 
          overhead += (sizeof (page_entry) - sizeof (long)
                       + BITMAP_SIZE (OBJECTS_PER_PAGE (i) + 1));