aboutsummaryrefslogtreecommitdiff
path: root/gcc/ggc-zone.c
diff options
context:
space:
mode:
authorDaniel Berlin <dberlin@dberlin.org>2004-01-05 19:23:50 +0000
committerDaniel Berlin <dberlin@gcc.gnu.org>2004-01-05 19:23:50 +0000
commit02fef8539ebbe2e8d71f1c8fcb699942e4e0cfdb (patch)
tree5aaaedfdf436558d04931e3b3bbb509a847af114 /gcc/ggc-zone.c
parentab22bc9148e058a649bc50cb0bdc160a9ead763b (diff)
downloadgcc-02fef8539ebbe2e8d71f1c8fcb699942e4e0cfdb.zip
gcc-02fef8539ebbe2e8d71f1c8fcb699942e4e0cfdb.tar.gz
gcc-02fef8539ebbe2e8d71f1c8fcb699942e4e0cfdb.tar.bz2
ggc-zone.c: Remove everything in #ifdef USING_MALLOC_PAGE_GROUPS
2004-01-05 Daniel Berlin <dberlin@dberlin.org> * ggc-zone.c: Remove everything in #ifdef USING_MALLOC_PAGE_GROUPS (USING_MMAP): We don't support non-mmap. (struct alloc_chunk): Steal 1 bit from typecode, use it to mark large objects. (struct page_entry): Remove bytes_free. (struct page_table_chain): Remove. (struct globals): Remove page_table member. (loookup_page_table_entry): Function deleted. (set_page_table_entry): Ditto. (ggc_allocated_p): No longer need page table lookups. (ggc_marked_p): Ditto. (alloc_small_page): Don't care about bytes_free anymore. (alloc_large_page): Round up size. (ggc_alloc_zone_1): Mark large objects as such, and calculate their size the new way. Remove page table lookups and setting. (ggc_get_size): Calculate large object size the new way. (sweep_pages): Redo to account for fact that we no longer have bytes_free. (ggc_collect): No longer need to reincrement bytes_free. (ggc_pch_alloc_object): Handle new large objects properly. (ggc_pch_read): Put PCH stuff into it's own uncollected zone. From-SVN: r75438
Diffstat (limited to 'gcc/ggc-zone.c')
-rw-r--r--gcc/ggc-zone.c485
1 files changed, 62 insertions, 423 deletions
diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c
index a709edf..5a7d6d4 100644
--- a/gcc/ggc-zone.c
+++ b/gcc/ggc-zone.c
@@ -1,6 +1,7 @@
/* "Bag-of-pages" zone garbage collector for the GNU compiler.
Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
- Contributed by Richard Henderson (rth@redhat.com) and Daniel Berlin (dberlin@dberlin.org)
+ Contributed by Richard Henderson (rth@redhat.com) and Daniel Berlin
+ (dberlin@dberlin.org)
This file is part of GCC.
@@ -76,7 +77,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#endif
#ifndef USING_MMAP
-#define USING_MALLOC_PAGE_GROUPS
+#error "Zone collector requires mmap"
#endif
#if (GCC_VERSION < 3001)
@@ -143,7 +144,8 @@ struct alloc_chunk {
unsigned int magic;
#endif
unsigned int type:1;
- unsigned int typecode:15;
+ unsigned int typecode:14;
+ unsigned int large:1;
unsigned int size:15;
unsigned int mark:1;
union {
@@ -211,38 +213,6 @@ struct max_alignment {
#define ROUND_UP(x, f) (CEIL (x, f) * (f))
-/* A two-level tree is used to look up the page-entry for a given
- pointer. Two chunks of the pointer's bits are extracted to index
- the first and second levels of the tree, as follows:
-
- HOST_PAGE_SIZE_BITS
- 32 | |
- msb +----------------+----+------+------+ lsb
- | | |
- PAGE_L1_BITS |
- | |
- PAGE_L2_BITS
-
- The bottommost HOST_PAGE_SIZE_BITS are ignored, since page-entry
- pages are aligned on system page boundaries. The next most
- significant PAGE_L2_BITS and PAGE_L1_BITS are the second and first
- index values in the lookup table, respectively.
-
- For 32-bit architectures and the settings below, there are no
- leftover bits. For architectures with wider pointers, the lookup
- tree points to a list of pages, which must be scanned to find the
- correct one. */
-
-#define PAGE_L1_BITS (8)
-#define PAGE_L2_BITS (32 - PAGE_L1_BITS - G.lg_pagesize)
-#define PAGE_L1_SIZE ((size_t) 1 << PAGE_L1_BITS)
-#define PAGE_L2_SIZE ((size_t) 1 << PAGE_L2_BITS)
-
-#define LOOKUP_L1(p) \
- (((size_t) (p) >> (32 - PAGE_L1_BITS)) & ((1 << PAGE_L1_BITS) - 1))
-
-#define LOOKUP_L2(p) \
- (((size_t) (p) >> G.lg_pagesize) & ((1 << PAGE_L2_BITS) - 1))
/* A page_entry records the status of an allocation page. */
typedef struct page_entry
@@ -261,15 +231,6 @@ typedef struct page_entry
/* The address at which the memory is allocated. */
char *page;
-#ifdef USING_MALLOC_PAGE_GROUPS
- /* Back pointer to the page group this page came from. */
- struct page_group *group;
-#endif
-
- /* Number of bytes on the page unallocated. Only used during
- collection, and even then large pages merely set this nonzero. */
- size_t bytes_free;
-
/* Context depth of this page. */
unsigned short context_depth;
@@ -280,50 +241,10 @@ typedef struct page_entry
struct alloc_zone *zone;
} page_entry;
-#ifdef USING_MALLOC_PAGE_GROUPS
-/* A page_group describes a large allocation from malloc, from which
- we parcel out aligned pages. */
-typedef struct page_group
-{
- /* A linked list of all extant page groups. */
- struct page_group *next;
-
- /* The address we received from malloc. */
- char *allocation;
-
- /* The size of the block. */
- size_t alloc_size;
-
- /* A bitmask of pages in use. */
- unsigned int in_use;
-} page_group;
-#endif
-
-#if HOST_BITS_PER_PTR <= 32
-
-/* On 32-bit hosts, we use a two level page table, as pictured above. */
-typedef page_entry **page_table[PAGE_L1_SIZE];
-
-#else
-
-/* On 64-bit hosts, we use the same two level page tables plus a linked
- list that disambiguates the top 32-bits. There will almost always be
- exactly one entry in the list. */
-typedef struct page_table_chain
-{
- struct page_table_chain *next;
- size_t high_bits;
- page_entry **table[PAGE_L1_SIZE];
-} *page_table;
-
-#endif
/* The global variables. */
static struct globals
{
- /* The page lookup table. A single page can only belong to one
- zone. This means free pages are zone-specific ATM. */
- page_table lookup;
/* The linked list of zones. */
struct alloc_zone *zones;
@@ -374,10 +295,6 @@ struct alloc_zone
/* A cache of free system pages. */
page_entry *free_pages;
-#ifdef USING_MALLOC_PAGE_GROUPS
- page_group *page_groups;
-#endif
-
/* Next zone in the linked list of zones. */
struct alloc_zone *next_zone;
@@ -399,16 +316,9 @@ struct alloc_zone *tree_zone;
#define GGC_QUIRE_SIZE 16
static int ggc_allocated_p (const void *);
-static page_entry *lookup_page_table_entry (const void *);
-static void set_page_table_entry (void *, page_entry *);
#ifdef USING_MMAP
static char *alloc_anon (char *, size_t, struct alloc_zone *);
#endif
-#ifdef USING_MALLOC_PAGE_GROUPS
-static size_t page_group_index (char *, char *);
-static void set_page_group_in_use (page_group *, char *);
-static void clear_page_group_in_use (page_group *, char *);
-#endif
static struct page_entry * alloc_small_page ( struct alloc_zone *);
static struct page_entry * alloc_large_page (size_t, struct alloc_zone *);
static void free_chunk (struct alloc_chunk *, size_t, struct alloc_zone *);
@@ -425,94 +335,17 @@ static void check_cookies (void);
static inline int
ggc_allocated_p (const void *p)
{
- page_entry ***base;
- size_t L1, L2;
-
-#if HOST_BITS_PER_PTR <= 32
- base = &G.lookup[0];
-#else
- page_table table = G.lookup;
- size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
- while (1)
- {
- if (table == NULL)
- return 0;
- if (table->high_bits == high_bits)
- break;
- table = table->next;
- }
- base = &table->table[0];
-#endif
-
- /* Extract the level 1 and 2 indices. */
- L1 = LOOKUP_L1 (p);
- L2 = LOOKUP_L2 (p);
-
- return base[L1] && base[L1][L2];
-}
-
-/* Traverse the page table and find the entry for a page.
- Die (probably) if the object wasn't allocated via GC. */
-
-static inline page_entry *
-lookup_page_table_entry(const void *p)
-{
- page_entry ***base;
- size_t L1, L2;
-
-#if HOST_BITS_PER_PTR <= 32
- base = &G.lookup[0];
-#else
- page_table table = G.lookup;
- size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
- while (table->high_bits != high_bits)
- table = table->next;
- base = &table->table[0];
+ struct alloc_chunk *chunk;
+ chunk = (struct alloc_chunk *) ((char *)p - CHUNK_OVERHEAD);
+#ifdef COOKIE_CHECKING
+ if (chunk->magic != CHUNK_MAGIC)
+ abort ();
#endif
-
- /* Extract the level 1 and 2 indices. */
- L1 = LOOKUP_L1 (p);
- L2 = LOOKUP_L2 (p);
-
- return base[L1][L2];
-
+ if (chunk->type == 1)
+ return true;
+ return false;
}
-/* Set the page table entry for a page. */
-
-static void
-set_page_table_entry(void *p, page_entry *entry)
-{
- page_entry ***base;
- size_t L1, L2;
-
-#if HOST_BITS_PER_PTR <= 32
- base = &G.lookup[0];
-#else
- page_table table;
- size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
- for (table = G.lookup; table; table = table->next)
- if (table->high_bits == high_bits)
- goto found;
-
- /* Not found -- allocate a new table. */
- table = (page_table) xcalloc (1, sizeof(*table));
- table->next = G.lookup;
- table->high_bits = high_bits;
- G.lookup = table;
-found:
- base = &table->table[0];
-#endif
-
- /* Extract the level 1 and 2 indices. */
- L1 = LOOKUP_L1 (p);
- L2 = LOOKUP_L2 (p);
-
- if (base[L1] == NULL)
- base[L1] = (page_entry **) xcalloc (PAGE_L2_SIZE, sizeof (page_entry *));
-
- base[L1][L2] = entry;
-}
#ifdef USING_MMAP
/* Allocate SIZE bytes of anonymous memory, preferably near PREF,
@@ -547,42 +380,15 @@ alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size, struct alloc_zone *zone)
return page;
}
#endif
-#ifdef USING_MALLOC_PAGE_GROUPS
-/* Compute the index for this page into the page group. */
-
-static inline size_t
-page_group_index (char *allocation, char *page)
-{
- return (size_t) (page - allocation) >> G.lg_pagesize;
-}
-
-/* Set and clear the in_use bit for this page in the page group. */
-
-static inline void
-set_page_group_in_use (page_group *group, char *page)
-{
- group->in_use |= 1 << page_group_index (group->allocation, page);
-}
-
-static inline void
-clear_page_group_in_use (page_group *group, char *page)
-{
- group->in_use &= ~(1 << page_group_index (group->allocation, page));
-}
-#endif
/* Allocate a new page for allocating objects of size 2^ORDER,
- and return an entry for it. The entry is not added to the
- appropriate page_table list. */
+ and return an entry for it. */
static inline struct page_entry *
alloc_small_page (struct alloc_zone *zone)
{
struct page_entry *entry;
char *page;
-#ifdef USING_MALLOC_PAGE_GROUPS
- page_group *group;
-#endif
page = NULL;
@@ -594,9 +400,7 @@ alloc_small_page (struct alloc_zone *zone)
zone->free_pages = entry->next;
page = entry->page;
-#ifdef USING_MALLOC_PAGE_GROUPS
- group = entry->group;
-#endif
+
}
#ifdef USING_MMAP
else
@@ -623,97 +427,17 @@ alloc_small_page (struct alloc_zone *zone)
zone->free_pages = f;
}
#endif
-#ifdef USING_MALLOC_PAGE_GROUPS
- else
- {
- /* Allocate a large block of memory and serve out the aligned
- pages therein. This results in much less memory wastage
- than the traditional implementation of valloc. */
-
- char *allocation, *a, *enda;
- size_t alloc_size, head_slop, tail_slop;
- int multiple_pages = (entry_size == G.pagesize);
-
- if (multiple_pages)
- alloc_size = GGC_QUIRE_SIZE * G.pagesize;
- else
- alloc_size = entry_size + G.pagesize - 1;
- allocation = xmalloc (alloc_size);
- VALGRIND_MALLOCLIKE_BLOCK(addr, alloc_size, 0, 0);
-
- page = (char *) (((size_t) allocation + G.pagesize - 1) & -G.pagesize);
- head_slop = page - allocation;
- if (multiple_pages)
- tail_slop = ((size_t) allocation + alloc_size) & (G.pagesize - 1);
- else
- tail_slop = alloc_size - entry_size - head_slop;
- enda = allocation + alloc_size - tail_slop;
-
- /* We allocated N pages, which are likely not aligned, leaving
- us with N-1 usable pages. We plan to place the page_group
- structure somewhere in the slop. */
- if (head_slop >= sizeof (page_group))
- group = (page_group *)page - 1;
- else
- {
- /* We magically got an aligned allocation. Too bad, we have
- to waste a page anyway. */
- if (tail_slop == 0)
- {
- enda -= G.pagesize;
- tail_slop += G.pagesize;
- }
- if (tail_slop < sizeof (page_group))
- abort ();
- group = (page_group *)enda;
- tail_slop -= sizeof (page_group);
- }
-
- /* Remember that we allocated this memory. */
- group->next = G.page_groups;
- group->allocation = allocation;
- group->alloc_size = alloc_size;
- group->in_use = 0;
- zone->page_groups = group;
- G.bytes_mapped += alloc_size;
-
- /* If we allocated multiple pages, put the rest on the free list. */
- if (multiple_pages)
- {
- struct page_entry *e, *f = G.free_pages;
- for (a = enda - G.pagesize; a != page; a -= G.pagesize)
- {
- e = (struct page_entry *) xmalloc (sizeof (struct page_entry));
- e->bytes = G.pagesize;
- e->page = a;
- e->group = group;
- e->next = f;
- f = e;
- }
- zone->free_pages = f;
- }
- }
-#endif
-
if (entry == NULL)
entry = (struct page_entry *) xmalloc (sizeof (struct page_entry));
entry->next = 0;
entry->bytes = G.pagesize;
- entry->bytes_free = G.pagesize;
entry->page = page;
entry->context_depth = zone->context_depth;
entry->large_p = false;
entry->zone = zone;
zone->context_depth_allocations |= (unsigned long)1 << zone->context_depth;
-#ifdef USING_MALLOC_PAGE_GROUPS
- entry->group = group;
- set_page_group_in_use (group, page);
-#endif
-
- set_page_table_entry (page, entry);
-
if (GGC_DEBUG_LEVEL >= 2)
fprintf (G.debug_file,
"Allocating %s page at %p, data %p-%p\n", entry->zone->name,
@@ -721,6 +445,9 @@ alloc_small_page (struct alloc_zone *zone)
return entry;
}
+/* Compute the smallest multiple of F that is >= X. */
+
+#define ROUND_UP(x, f) (CEIL (x, f) * (f))
/* Allocate a large page of size SIZE in ZONE. */
@@ -729,24 +456,18 @@ alloc_large_page (size_t size, struct alloc_zone *zone)
{
struct page_entry *entry;
char *page;
-
+ size = ROUND_UP (size, 1024);
page = (char *) xmalloc (size + CHUNK_OVERHEAD + sizeof (struct page_entry));
entry = (struct page_entry *) (page + size + CHUNK_OVERHEAD);
entry->next = 0;
entry->bytes = size;
- entry->bytes_free = LARGE_OBJECT_SIZE + CHUNK_OVERHEAD;
entry->page = page;
entry->context_depth = zone->context_depth;
entry->large_p = true;
entry->zone = zone;
zone->context_depth_allocations |= (unsigned long)1 << zone->context_depth;
-#ifdef USING_MALLOC_PAGE_GROUPS
- entry->group = NULL;
-#endif
- set_page_table_entry (page, entry);
-
if (GGC_DEBUG_LEVEL >= 2)
fprintf (G.debug_file,
"Allocating %s large page at %p, data %p-%p\n", entry->zone->name,
@@ -766,8 +487,6 @@ free_page (page_entry *entry)
"Deallocating %s page at %p, data %p-%p\n", entry->zone->name, (PTR) entry,
entry->page, entry->page + entry->bytes - 1);
- set_page_table_entry (entry->page, NULL);
-
if (entry->large_p)
{
free (entry->page);
@@ -779,10 +498,6 @@ free_page (page_entry *entry)
avoid handle leak. */
VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (entry->page, entry->bytes));
-#ifdef USING_MALLOC_PAGE_GROUPS
- clear_page_group_in_use (entry->group, entry->page);
-#endif
-
entry->next = entry->zone->free_pages;
entry->zone->free_pages = entry;
}
@@ -823,34 +538,6 @@ release_pages (struct alloc_zone *zone)
zone->free_pages = NULL;
#endif
-#ifdef USING_MALLOC_PAGE_GROUPS
- page_entry **pp, *p;
- page_group **gp, *g;
-
- /* Remove all pages from free page groups from the list. */
- pp = &(zone->free_pages);
- while ((p = *pp) != NULL)
- if (p->group->in_use == 0)
- {
- *pp = p->next;
- free (p);
- }
- else
- pp = &p->next;
-
- /* Remove all free page groups, and release the storage. */
- gp = &(zone->page_groups);
- while ((g = *gp) != NULL)
- if (g->in_use == 0)
- {
- *gp = g->next;
- zone->bytes_mapped -= g->alloc_size;
- free (g->allocation);
- VALGRIND_FREELIKE_BLOCK(g->allocation, 0);
- }
- else
- gp = &g->next;
-#endif
}
/* Place CHUNK of size SIZE on the free list for ZONE. */
@@ -896,15 +583,16 @@ ggc_alloc_zone_1 (size_t size, struct alloc_zone *zone, short type)
/* Large objects are handled specially. */
if (size >= G.pagesize - 2*CHUNK_OVERHEAD - FREE_BIN_DELTA)
{
+ size = ROUND_UP (size, 1024);
entry = alloc_large_page (size, zone);
entry->survived = 0;
entry->next = entry->zone->pages;
entry->zone->pages = entry;
-
chunk = (struct alloc_chunk *) entry->page;
VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (chunk, sizeof (struct alloc_chunk)));
- chunk->size = LARGE_OBJECT_SIZE;
+ chunk->large = 1;
+ chunk->size = CEIL (size, 1024);
goto found;
}
@@ -943,11 +631,13 @@ ggc_alloc_zone_1 (size_t size, struct alloc_zone *zone, short type)
chunk = (struct alloc_chunk *) entry->page;
VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (chunk, sizeof (struct alloc_chunk)));
chunk->size = G.pagesize - CHUNK_OVERHEAD;
+ chunk->large = 0;
}
else
{
*pp = chunk->u.next_free;
VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (chunk, sizeof (struct alloc_chunk)));
+ chunk->large = 0;
}
/* Release extra memory from a chunk that's too big. */
lsize = chunk->size - size;
@@ -965,6 +655,7 @@ ggc_alloc_zone_1 (size_t size, struct alloc_zone *zone, short type)
lchunk->type = 0;
lchunk->mark = 0;
lchunk->size = lsize;
+ lchunk->large = 0;
free_chunk (lchunk, lsize, zone);
}
/* Calculate the object's address. */
@@ -1049,16 +740,8 @@ ggc_alloc_zone (size_t size, struct alloc_zone *zone)
int
ggc_set_mark (const void *p)
{
- page_entry *entry;
struct alloc_chunk *chunk;
-#ifdef ENABLE_CHECKING
- /* Look up the page on which the object is alloced. If the object
- wasn't allocated by the collector, we'll probably die. */
- entry = lookup_page_table_entry (p);
- if (entry == NULL)
- abort ();
-#endif
chunk = (struct alloc_chunk *) ((char *)p - CHUNK_OVERHEAD);
#ifdef COOKIE_CHECKING
if (chunk->magic != CHUNK_MAGIC)
@@ -1068,17 +751,6 @@ ggc_set_mark (const void *p)
return 1;
chunk->mark = 1;
-#ifndef ENABLE_CHECKING
- entry = lookup_page_table_entry (p);
-#endif
-
- /* Large pages are either completely full or completely empty. So if
- they are marked, they are completely full. */
- if (entry->large_p)
- entry->bytes_free = 0;
- else
- entry->bytes_free -= chunk->size + CHUNK_OVERHEAD;
-
if (GGC_DEBUG_LEVEL >= 4)
fprintf (G.debug_file, "Marking %p\n", p);
@@ -1094,14 +766,6 @@ ggc_marked_p (const void *p)
{
struct alloc_chunk *chunk;
-#ifdef ENABLE_CHECKING
- {
- page_entry *entry = lookup_page_table_entry (p);
- if (entry == NULL)
- abort ();
- }
-#endif
-
chunk = (struct alloc_chunk *) ((char *)p - CHUNK_OVERHEAD);
#ifdef COOKIE_CHECKING
if (chunk->magic != CHUNK_MAGIC)
@@ -1116,26 +780,14 @@ size_t
ggc_get_size (const void *p)
{
struct alloc_chunk *chunk;
- struct page_entry *entry;
-
-#ifdef ENABLE_CHECKING
- entry = lookup_page_table_entry (p);
- if (entry == NULL)
- abort ();
-#endif
chunk = (struct alloc_chunk *) ((char *)p - CHUNK_OVERHEAD);
#ifdef COOKIE_CHECKING
if (chunk->magic != CHUNK_MAGIC)
abort ();
#endif
- if (chunk->size == LARGE_OBJECT_SIZE)
- {
-#ifndef ENABLE_CHECKING
- entry = lookup_page_table_entry (p);
-#endif
- return entry->bytes;
- }
+ if (chunk->large)
+ return chunk->size * 1024;
return chunk->size;
}
@@ -1278,8 +930,6 @@ ggc_pop_context (void)
for (zone = G.zones; zone; zone = zone->next_zone)
ggc_pop_context_1 (zone);
}
-
-
/* Poison the chunk. */
#ifdef ENABLE_GC_CHECKING
#define poison_chunk(CHUNK, SIZE) \
@@ -1296,7 +946,7 @@ sweep_pages (struct alloc_zone *zone)
page_entry **pp, *p, *next;
struct alloc_chunk *chunk, *last_free, *end;
size_t last_free_size, allocated = 0;
-
+ bool nomarksinpage;
/* First, reset the free_chunks lists, since we are going to
re-free free chunks in hopes of coalescing them into large chunks. */
memset (zone->free_chunks, 0, sizeof (zone->free_chunks));
@@ -1304,32 +954,27 @@ sweep_pages (struct alloc_zone *zone)
for (p = zone->pages; p ; p = next)
{
next = p->next;
-
- /* For empty pages, just free the page. */
- if (p->bytes_free == G.pagesize && p->context_depth == zone->context_depth)
+ /* Large pages are all or none affairs. Either they are
+ completely empty, or they are completely full.
+
+ XXX: Should we bother to increment allocated. */
+ if (p->large_p)
{
- *pp = next;
+ if (((struct alloc_chunk *)p->page)->mark == 1)
+ {
+ ((struct alloc_chunk *)p->page)->mark = 0;
+ }
+ else
+ {
+ *pp = next;
#ifdef ENABLE_GC_CHECKING
/* Poison the page. */
memset (p->page, 0xb5, p->bytes);
#endif
- free_page (p);
- continue;
- }
-
- /* Large pages are all or none affairs. Either they are
- completely empty, or they are completely full.
- Thus, if the above didn't catch it, we need not do anything
- except remove the mark and reset the bytes_free.
-
- XXX: Should we bother to increment allocated. */
- else if (p->large_p)
- {
- p->bytes_free = p->bytes;
- ((struct alloc_chunk *)p->page)->mark = 0;
+ free_page (p);
+ }
continue;
}
- pp = &p->next;
/* This page has now survived another collection. */
p->survived++;
@@ -1343,12 +988,13 @@ sweep_pages (struct alloc_zone *zone)
end = (struct alloc_chunk *)(p->page + G.pagesize);
last_free = NULL;
last_free_size = 0;
-
+ nomarksinpage = true;
do
{
prefetch ((struct alloc_chunk *)(chunk->u.data + chunk->size));
if (chunk->mark || p->context_depth < zone->context_depth)
{
+ nomarksinpage = false;
if (last_free)
{
last_free->type = 0;
@@ -1361,13 +1007,8 @@ sweep_pages (struct alloc_zone *zone)
if (chunk->mark)
{
allocated += chunk->size + CHUNK_OVERHEAD;
- p->bytes_free += chunk->size + CHUNK_OVERHEAD;
}
chunk->mark = 0;
-#ifdef ENABLE_CHECKING
- if (p->bytes_free > p->bytes)
- abort ();
-#endif
}
else
{
@@ -1386,7 +1027,17 @@ sweep_pages (struct alloc_zone *zone)
}
while (chunk < end);
- if (last_free)
+ if (nomarksinpage)
+ {
+ *pp = next;
+#ifdef ENABLE_GC_CHECKING
+ /* Poison the page. */
+ memset (p->page, 0xb5, p->bytes);
+#endif
+ free_page (p);
+ continue;
+ }
+ else if (last_free)
{
last_free->type = 0;
last_free->size = last_free_size;
@@ -1394,6 +1045,7 @@ sweep_pages (struct alloc_zone *zone)
poison_chunk (last_free, last_free_size);
free_chunk (last_free, last_free_size, zone);
}
+ pp = &p->next;
}
zone->allocated = allocated;
@@ -1496,8 +1148,6 @@ check_cookies (void)
}
#endif
}
-
-
/* Top level collection routine. */
void
@@ -1569,12 +1219,6 @@ ggc_collect (void)
prefetch ((struct alloc_chunk *)(chunk->u.data + chunk->size));
if (chunk->mark || p->context_depth < zone->context_depth)
{
- if (chunk->mark)
- p->bytes_free += chunk->size + CHUNK_OVERHEAD;
-#ifdef ENABLE_CHECKING
- if (p->bytes_free > p->bytes)
- abort ();
-#endif
chunk->mark = 0;
}
chunk = (struct alloc_chunk *)(chunk->u.data + chunk->size);
@@ -1583,7 +1227,6 @@ ggc_collect (void)
}
else
{
- p->bytes_free = p->bytes;
((struct alloc_chunk *)p->page)->mark = 0;
}
}
@@ -1679,7 +1322,7 @@ ggc_pch_alloc_object (struct ggc_pch_data *d, void *x,
if (!is_string)
{
struct alloc_chunk *chunk = (struct alloc_chunk *) ((char *)x - CHUNK_OVERHEAD);
- if (chunk->size == LARGE_OBJECT_SIZE)
+ if (chunk->large)
d->base += ggc_get_size (x) + CHUNK_OVERHEAD;
else
d->base += chunk->size + CHUNK_OVERHEAD;
@@ -1735,24 +1378,20 @@ ggc_pch_finish (struct ggc_pch_data *d, FILE *f)
fatal_error ("can't write PCH file: %m");
free (d);
}
-
-
void
ggc_pch_read (FILE *f, void *addr)
{
struct ggc_pch_ondisk d;
struct page_entry *entry;
- char *pte;
+ struct alloc_zone *pch_zone;
if (fread (&d, sizeof (d), 1, f) != 1)
fatal_error ("can't read PCH file: %m");
entry = xcalloc (1, sizeof (struct page_entry));
entry->bytes = d.total;
entry->page = addr;
entry->context_depth = 0;
- entry->zone = &main_zone;
- for (pte = entry->page;
- pte < entry->page + entry->bytes;
- pte += G.pagesize)
- set_page_table_entry (pte, entry);
-
+ pch_zone = new_ggc_zone ("PCH zone");
+ entry->zone = pch_zone;
+ entry->next = entry->zone->pages;
+ entry->zone->pages = entry;
}