From: dberlin Date: Mon, 5 Jan 2004 19:23:50 +0000 (+0000) Subject: 2004-01-05 Daniel Berlin X-Git-Tag: upstream/4.9.2~74282 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=211e9ed72e637f1f95557fd687e46458c0557eba;p=platform%2Fupstream%2Flinaro-gcc.git 2004-01-05 Daniel Berlin * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@75438 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ebf4345..09d6b9b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2004-01-05 Daniel Berlin + + * 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. + 2004-01-05 Kazu Hirata * doc/invoke.texi: Remove a page break. 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; }