Skip to content
Snippets Groups Projects
Commit bd46c00c authored by dtc's avatar dtc
Browse files

Improve the efficiency of gc_free_heap by having it assume free pages

are zero filled and not write protected which should be the case.

Make more of the consistency checks conditional and disable them all.
parent 5ce1a424
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Douglas Crosher, 1996, 1997. * Douglas Crosher, 1996, 1997.
* *
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.2 1997/11/29 20:32:41 dtc Exp $ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.3 1997/11/30 05:08:29 dtc Exp $
* */ * */
#include <stdio.h> #include <stdio.h>
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define gc_abort() lose("GC invariant lost! File \"%s\", line %d\n", \ #define gc_abort() lose("GC invariant lost! File \"%s\", line %d\n", \
__FILE__, __LINE__) __FILE__, __LINE__)
#if 1 #if 0
#define gc_assert(ex) do { \ #define gc_assert(ex) do { \
if (!(ex)) gc_abort(); \ if (!(ex)) gc_abort(); \
} while (0) } while (0)
...@@ -48,18 +48,24 @@ boolean enable_page_protection = TRUE; ...@@ -48,18 +48,24 @@ boolean enable_page_protection = TRUE;
/* Hunt for pointers to old-space, when GCing generations >= /* Hunt for pointers to old-space, when GCing generations >=
verify_gen. Set to NUM_GENERATIONS to disable. */ verify_gen. Set to NUM_GENERATIONS to disable. */
int verify_gens = NUM_GENERATIONS-1; int verify_gens = NUM_GENERATIONS;
/* Enable a pre-scan verify of generation 0 before it's GCed */ /* Enable a pre-scan verify of generation 0 before it's GCed */
boolean pre_verify_gen_0 = FALSE; boolean pre_verify_gen_0 = FALSE;
/*
* Enable checking for bad pointers after gc_free_heap called
* from purify
*/
boolean verify_after_free_heap = FALSE;
/* Enable the printing of a note when code objects are found in the /* Enable the printing of a note when code objects are found in the
dynamic space during a heap verify. */ dynamic space during a heap verify. */
boolean verify_dynamic_code_check = FALSE; boolean verify_dynamic_code_check = FALSE;
/* Enable the checking of code objects for fixup errors after they are /* Enable the checking of code objects for fixup errors after they are
transported. */ transported. */
boolean check_code_fixups = TRUE; boolean check_code_fixups = FALSE;
/* To enable unmapping of a page and re-mmaping it to have it zero /* To enable unmapping of a page and re-mmaping it to have it zero
filled. */ filled. */
...@@ -73,6 +79,12 @@ boolean gencgc_unmap_zero = TRUE; ...@@ -73,6 +79,12 @@ boolean gencgc_unmap_zero = TRUE;
/* Enable checking that newly allocated regions are zero filled. */ /* Enable checking that newly allocated regions are zero filled. */
boolean gencgc_zero_check = FALSE; boolean gencgc_zero_check = FALSE;
/*
* Enable checking that free pages are zero filled during gc_free_heap
* called after purify.
*/
boolean gencgc_zero_check_during_free_heap = FALSE;
/* The minimum size for a large object. */ /* The minimum size for a large object. */
unsigned large_object_size = 4*4096; unsigned large_object_size = 4*4096;
...@@ -1778,6 +1790,9 @@ sniff_code_object(struct code *code, unsigned displacement) ...@@ -1778,6 +1790,9 @@ sniff_code_object(struct code *code, unsigned displacement)
void *code_start_addr, *code_end_addr; void *code_start_addr, *code_end_addr;
int fixup_found = 0; int fixup_found = 0;
if (!check_code_fixups)
return;
/* It's ok if it's byte compiled code. The trace /* It's ok if it's byte compiled code. The trace
table offset will be a fixnum if it's x86 table offset will be a fixnum if it's x86
compiled code - check. */ compiled code - check. */
...@@ -5497,53 +5512,67 @@ collect_garbage(unsigned last_gen) ...@@ -5497,53 +5512,67 @@ collect_garbage(unsigned last_gen)
have been moved to the RO and Static heaps. The dynamic space will have been moved to the RO and Static heaps. The dynamic space will
need a full re-initialisation. I don't bother having purify flush need a full re-initialisation. I don't bother having purify flush
the current gc_alloc region, as the page_tables are re-initialised, the current gc_alloc region, as the page_tables are re-initialised,
and every page zeroed to be sure. and every page is zeroed to be sure.
*/ */
void void
gc_free_heap(void) gc_free_heap(void)
{ {
unsigned long allocated = bytes_allocated; unsigned long allocated = bytes_allocated;
int i; int page;
if (gencgc_verbose) if (gencgc_verbose)
fprintf(stderr,"Free heap\n"); fprintf(stderr,"Free heap\n");
for (i = 0; i < NUM_PAGES; i++) { for (page = 0; page < NUM_PAGES; page++)
void *page_start, *addr; /* Skip Free pages which should already be zero filled. */
if (page_table[page].allocated != FREE_PAGE) {
/* Mark the page free. The other slots are assumed invalid when it void *page_start, *addr;
is a FREE_PAGE and bytes_used is 0 and it should not be write
protected - except that the generation is used for the current /* Mark the page free. The other slots are assumed invalid when it
region but it sets that up. */ is a FREE_PAGE and bytes_used is 0 and it should not be write
page_table[i].allocated = FREE_PAGE; protected - except that the generation is used for the current
page_table[i].bytes_used = 0; region but it sets that up. */
page_table[page].allocated = FREE_PAGE;
/* Zero the page. */ page_table[page].bytes_used = 0;
page_start = (void *)page_address(i);
/* Zero the page. */
/* First remove any write protection */ page_start = (void *)page_address(page);
os_protect(page_start, 4096, OS_VM_PROT_ALL);
page_table[i].write_protected = 0; /* First remove any write protection */
os_protect(page_start, 4096, OS_VM_PROT_ALL);
os_invalidate(page_start,4096); page_table[page].write_protected = 0;
addr = os_validate(page_start,4096);
if(addr == NULL || addr != page_start) os_invalidate(page_start,4096);
fprintf(stderr,"gc_zero: page moved, 0x%08x ==> 0x%08x!\n", addr = os_validate(page_start,4096);
page_start,addr); if(addr == NULL || addr != page_start)
} fprintf(stderr,"gc_zero: page moved, 0x%08x ==> 0x%08x!\n",
page_start,addr);
} else if (gencgc_zero_check_during_free_heap) {
int *page_start, i;
/* Double check that the page is zero filled. */
gc_assert(page_table[page].allocated == FREE_PAGE);
gc_assert(page_table[page].bytes_used == 0);
page_start = (int *)page_address(i);
for(i=0; i<1024; i++)
if (page_start[i] != 0)
fprintf(stderr,"** Free region not zero @ %x\n", page_start+i);
}
bytes_allocated = 0; bytes_allocated = 0;
/* Initialise the generations. */ /* Initialise the generations. */
for (i = 0; i < NUM_GENERATIONS; i++) { for (page = 0; page < NUM_GENERATIONS; page++) {
generations[i].alloc_start_page = 0; generations[page].alloc_start_page = 0;
generations[i].alloc_unboxed_start_page = 0; generations[page].alloc_unboxed_start_page = 0;
generations[i].alloc_large_start_page = 0; generations[page].alloc_large_start_page = 0;
generations[i].alloc_large_unboxed_start_page = 0; generations[page].alloc_large_unboxed_start_page = 0;
generations[i].bytes_allocated = 0; generations[page].bytes_allocated = 0;
generations[i].gc_trigger = 2000000; generations[page].gc_trigger = 2000000;
generations[i].num_gc = 0; generations[page].num_gc = 0;
generations[i].cum_sum_bytes_allocated = 0; generations[page].cum_sum_bytes_allocated = 0;
} }
if (gencgc_verbose) if (gencgc_verbose)
...@@ -5573,9 +5602,11 @@ gc_free_heap(void) ...@@ -5573,9 +5602,11 @@ gc_free_heap(void)
current_region_free_pointer = boxed_region.free_pointer; current_region_free_pointer = boxed_region.free_pointer;
current_region_end_addr = boxed_region.end_addr; current_region_end_addr = boxed_region.end_addr;
/* Check if purify has left any bad pointers. */ if (verify_after_free_heap) {
fprintf(stderr,"Checking after free_heap.\n"); /* Check if purify has left any bad pointers. */
verify_gc(); fprintf(stderr,"Checking after free_heap.\n");
verify_gc();
}
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment