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
This commit is contained in:
Mark Mitchell 2001-01-04 21:18:27 +00:00 committed by Mark Mitchell
parent bf1aaf0ac6
commit 2be510b877
2 changed files with 116 additions and 34 deletions

View 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.

View 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);
}
/* 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));