From 2be510b87745ef8f57b584fdff4a2805783b3de7 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 4 Jan 2001 21:18:27 +0000 Subject: [PATCH] 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. From-SVN: r38692 --- gcc/ChangeLog | 28 ++++++++++++ gcc/ggc-page.c | 122 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 116 insertions(+), 34 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d37423bc50c..d422a7b06f1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2001-01-04 Mark Mitchell + + 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 * varasm.c (output_constructor): Use HOST_WIDE_INT for sizes. diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index 2b64f45db53..e4bf283498e 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -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); } /* 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));