X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fruntime%2Fgencgc.c;h=acc956c26575052740250375e1310437d5b716b4;hb=4cf50b1896b25f5337e7c258b0b560da00d47993;hp=a4766868b8b82d50ea1bab3e3a23d9ae902c8684;hpb=a530bbe337109d898d5b4a001fc8f1afa3b5dc39;p=sbcl.git diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index a476686..acc956c 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -14,10 +14,6 @@ */ /* - * $Header$ - */ - -/* * For a review of garbage collection techniques (e.g. generational * GC) and terminology (e.g. "scavenging") see Paul R. Wilson, * "Uniprocessor Garbage Collection Techniques". As of 20000618, this @@ -40,10 +36,12 @@ #include "runtime.h" #include "sbcl.h" #include "os.h" +#include "interr.h" #include "globals.h" #include "interrupt.h" #include "validate.h" #include "lispregs.h" +#include "arch.h" #include "gc.h" #include "gencgc.h" @@ -66,10 +64,13 @@ boolean enable_page_protection = 1; /* Should we unmap a page and re-mmap it to have it zero filled? */ #if defined(__FreeBSD__) || defined(__OpenBSD__) -/* Note: this can waste a lot of swap on FreeBSD so don't unmap there. +/* comment from cmucl-2.4.8: This can waste a lot of swap on FreeBSD + * so don't unmap there. * - * Presumably this behavior exists on OpenBSD too, so don't unmap - * there either. -- WHN 20000727 */ + * The CMU CL comment didn't specify a version, but was probably an + * old version of FreeBSD (pre-4.0), so this might no longer be true. + * OTOH, if it is true, this behavior might exist on OpenBSD too, so + * for now we don't unmap there either. -- WHN 2001-04-07 */ boolean gencgc_unmap_zero = 0; #else boolean gencgc_unmap_zero = 1; @@ -365,27 +366,30 @@ print_generation_stats(int verbose) /* FIXME: should take FILE argument */ for (j = 0; j < last_free_page; j++) if (page_table[j].gen == i) { + /* Count the number of boxed pages within the given - * generation */ - if (page_table[j].allocated == BOXED_PAGE) + * generation. */ + if (page_table[j].allocated == BOXED_PAGE) { if (page_table[j].large_object) large_boxed_cnt++; else boxed_cnt++; - + } + /* Count the number of unboxed pages within the given - * generation */ - if (page_table[j].allocated == UNBOXED_PAGE) + * generation. */ + if (page_table[j].allocated == UNBOXED_PAGE) { if (page_table[j].large_object) large_unboxed_cnt++; else unboxed_cnt++; + } } gc_assert(generations[i].bytes_allocated == generation_bytes_allocated(i)); fprintf(stderr, - " %8d: %5d %5d %5d %5d %8d %5d %8d %4d %3d %7.4lf\n", + " %8d: %5d %5d %5d %5d %8d %5d %8d %4d %3d %7.4f\n", i, boxed_cnt, unboxed_cnt, large_boxed_cnt, large_unboxed_cnt, generations[i].bytes_allocated, @@ -396,7 +400,7 @@ print_generation_stats(int verbose) /* FIXME: should take FILE argument */ generations[i].num_gc, gen_av_mem_age(i)); } - fprintf(stderr," Total bytes allocated=%d\n", bytes_allocated); + fprintf(stderr," Total bytes allocated=%ld\n", bytes_allocated); fpu_restore(fpu_state); } @@ -690,7 +694,7 @@ struct new_area { int size; }; static struct new_area (*new_areas)[]; -static new_areas_index; +static int new_areas_index; int max_new_areas; /* Add a new area to new_areas. */ @@ -1195,6 +1199,7 @@ static void /* shouldn't happen */ gc_assert(0); + return((void *) NIL); /* dummy value: return something ... */ } /* Allocate space from the boxed_region. If there is not enough free @@ -1313,6 +1318,7 @@ static void /* shouldn't happen? */ gc_assert(0); + return((void *) NIL); /* dummy value: return something ... */ } static inline void @@ -1741,12 +1747,18 @@ copy_large_unboxed_object(lispobj object, int nwords) #define DIRECT_SCAV 0 +/* FIXME: Most calls end up going to a little trouble to compute an + * 'nwords' value. The system might be a little simpler if this + * function used an 'end' parameter instead. */ static void scavenge(lispobj *start, long nwords) { while (nwords > 0) { lispobj object; - int type, words_scavenged; +#if DIRECT_SCAV + int type; +#endif + int words_scavenged; object = *start; @@ -1767,7 +1779,7 @@ scavenge(lispobj *start, long nwords) lispobj first_word = *ptr; if (first_word == 0x01) { - /* Yep, there be a forwarding pointer. */ + /* Yes, there's a forwarding pointer. */ *start = ptr[1]; words_scavenged = 1; } @@ -1780,7 +1792,7 @@ scavenge(lispobj *start, long nwords) } } else { if ((object & 3) == 0) { - /* It's a fixnum. Real easy.. */ + /* It's a fixnum: really easy.. */ words_scavenged = 1; } else { /* It's some sort of header object or another. */ @@ -1912,8 +1924,6 @@ void sniff_code_object(struct code *code, unsigned displacement) { int nheader_words, ncode_words, nwords; - lispobj fheaderl; - struct function *fheaderp; void *p; void *constants_start_addr, *constants_end_addr; void *code_start_addr, *code_end_addr; @@ -2093,7 +2103,6 @@ apply_code_fixups(struct code *old_code, struct code *new_code) int nheader_words, ncode_words, nwords; void *constants_start_addr, *constants_end_addr; void *code_start_addr, *code_end_addr; - lispobj p; lispobj fixups = NIL; unsigned displacement = (unsigned)new_code - (unsigned)old_code; struct vector *fixups_vector; @@ -2533,7 +2542,6 @@ trans_list(lispobj object) { lispobj new_list_pointer; struct cons *cons, *new_cons; - int n = 0; lispobj cdr; gc_assert(from_space_p(object)); @@ -2879,12 +2887,14 @@ scav_vector(lispobj *where, lispobj object) { unsigned int kv_length; lispobj *kv_vector; - unsigned int length; + unsigned int length = 0; /* (0 = dummy to stop GCC warning) */ lispobj *hash_table; lispobj empty_symbol; - unsigned int *index_vector, *next_vector, *hash_vector; + unsigned int *index_vector = NULL; /* (NULL = dummy to stop GCC warning) */ + unsigned int *next_vector = NULL; /* (NULL = dummy to stop GCC warning) */ + unsigned int *hash_vector = NULL; /* (NULL = dummy to stop GCC warning) */ lispobj weak_p_obj; - unsigned next_vector_length; + unsigned next_vector_length = 0; /* FIXME: A comment explaining this would be nice. It looks as * though SB-VM:VECTOR-VALID-HASHING-SUBTYPE is set for EQ-based @@ -2918,12 +2928,12 @@ scav_vector(lispobj *where, lispobj object) * the hash table code reserves for marking empty slots. */ scavenge(where+3, 1); if (!Pointerp(where[3])) { - lose("not #:%EMPTY-HT-SLOT% symbol pointer: %x", where[3]); + lose("not empty-hash-table-slot symbol pointer: %x", where[3]); } empty_symbol = where[3]; /* fprintf(stderr,"* empty_symbol = %x\n", empty_symbol);*/ if (TypeOf(*(lispobj *)PTR(empty_symbol)) != type_SymbolHeader) { - lose("not a symbol where #:%EMPTY-HT-SLOT% expected: %x", + lose("not a symbol where empty-hash-table-slot symbol expected: %x", *(lispobj *)PTR(empty_symbol)); } @@ -3649,7 +3659,7 @@ static lispobj trans_weak_pointer(lispobj object) { lispobj copy; - struct weak_pointer *wp; + /* struct weak_pointer *wp; */ gc_assert(Pointerp(object)); @@ -3682,7 +3692,7 @@ void scan_weak_pointers(void) struct weak_pointer *wp; for (wp = weak_pointers; wp != NULL; wp = wp->next) { lispobj value = wp->value; - lispobj first, *first_pointer; + lispobj *first_pointer; first_pointer = (lispobj *)PTR(value); @@ -4050,7 +4060,7 @@ search_read_only_space(lispobj *pointer) static lispobj * search_static_space(lispobj *pointer) { - lispobj* start = (lispobj*)static_space; + lispobj* start = (lispobj*)STATIC_SPACE_START; lispobj* end = (lispobj*)SymbolValue(STATIC_SPACE_FREE_POINTER); if ((pointer < start) || (pointer >= end)) return NULL; @@ -4114,7 +4124,8 @@ valid_dynamic_space_pointer(lispobj *pointer) case type_FuncallableInstanceHeader: case type_ByteCodeFunction: case type_ByteCodeClosure: - if ((int)pointer != ((int)start_addr+type_FunctionPointer)) { + if ((unsigned)pointer != + ((unsigned)start_addr+type_FunctionPointer)) { if (gencgc_verbose) FSHOW((stderr, "/Wf2: %x %x %x\n", @@ -4131,7 +4142,8 @@ valid_dynamic_space_pointer(lispobj *pointer) } break; case type_ListPointer: - if ((int)pointer != ((int)start_addr+type_ListPointer)) { + if ((unsigned)pointer != + ((unsigned)start_addr+type_ListPointer)) { if (gencgc_verbose) FSHOW((stderr, "/Wl1: %x %x %x\n", @@ -4156,7 +4168,8 @@ valid_dynamic_space_pointer(lispobj *pointer) return 0; } case type_InstancePointer: - if ((int)pointer != ((int)start_addr+type_InstancePointer)) { + if ((unsigned)pointer != + ((unsigned)start_addr+type_InstancePointer)) { if (gencgc_verbose) FSHOW((stderr, "/Wi1: %x %x %x\n", @@ -4172,7 +4185,8 @@ valid_dynamic_space_pointer(lispobj *pointer) } break; case type_OtherPointer: - if ((int)pointer != ((int)start_addr+type_OtherPointer)) { + if ((unsigned)pointer != + ((int)start_addr+type_OtherPointer)) { if (gencgc_verbose) FSHOW((stderr, "/Wo1: %x %x %x\n", @@ -4308,9 +4322,6 @@ valid_dynamic_space_pointer(lispobj *pointer) static void maybe_adjust_large_object(lispobj *where) { - int tag; - lispobj *new; - lispobj *source, *dest; int first_page; int nwords; @@ -4481,8 +4492,12 @@ preserve_pointer(void *addr) region_allocation = page_table[addr_page_index].allocated; - /* Check the offset within the page */ - if (((int)addr & 0xfff) > page_table[addr_page_index].bytes_used) + /* Check the offset within the page. + * + * FIXME: The mask should have a symbolic name, and ideally should + * be derived from page size instead of hardwired to 0xfff. + * (Also fix other uses of 0xfff, elsewhere.) */ + if (((unsigned)addr & 0xfff) > page_table[addr_page_index].bytes_used) return; if (enable_pointer_filter && !valid_dynamic_space_pointer(addr)) @@ -4510,7 +4525,7 @@ preserve_pointer(void *addr) if ((page_table[addr_page_index].allocated == FREE_PAGE) || (page_table[addr_page_index].bytes_used == 0) /* Check the offset within the page. */ - || (((int)addr & 0xfff) + || (((unsigned)addr & 0xfff) > page_table[addr_page_index].bytes_used)) { FSHOW((stderr, "weird? ignore ptr 0x%x to freed area of large object\n", @@ -4588,14 +4603,20 @@ scavenge_thread_stacks(void) vector_length)); if (vector_length > 0) { lispobj *stack_pointer = (lispobj*)stack->data[0]; - if ((stack_pointer < control_stack) || - (stack_pointer > control_stack_end)) + if ((stack_pointer < (lispobj *)CONTROL_STACK_START) || + (stack_pointer > (lispobj *)CONTROL_STACK_END)) lose("invalid stack pointer %x", (unsigned)stack_pointer); - if ((stack_pointer > control_stack) && - (stack_pointer < control_stack_end)) { - unsigned int length = ((int)control_stack_end - - (int)stack_pointer) / 4; + if ((stack_pointer > (lispobj *)CONTROL_STACK_START) && + (stack_pointer < (lispobj *)CONTROL_STACK_END)) { + /* FIXME: Ick! + * (1) hardwired word length = 4; and as usual, + * when fixing this, check for other places + * with the same problem + * (2) calling it 'length' suggests bytes; + * perhaps 'size' instead? */ + unsigned int length = ((unsigned)CONTROL_STACK_END - + (unsigned)stack_pointer) / 4; int j; if (length >= vector_length) { lose("invalid stack size %d >= vector length %d", @@ -4961,12 +4982,10 @@ scavenge_newspace_generation(int generation) /* the new_areas array currently being written to by gc_alloc */ struct new_area (*current_new_areas)[] = &new_areas_1; int current_new_areas_index; - int current_new_areas_allocated; /* the new_areas created but the previous scavenge cycle */ struct new_area (*previous_new_areas)[] = NULL; int previous_new_areas_index; - int previous_new_areas_allocated; #define SC_NS_GEN_CK 0 #if SC_NS_GEN_CK @@ -5099,14 +5118,13 @@ scavenge_newspace_generation(int generation) static void unprotect_oldspace(void) { - int bytes_freed = 0; int i; for (i = 0; i < last_free_page; i++) { if ((page_table[i].allocated != FREE_PAGE) && (page_table[i].bytes_used != 0) && (page_table[i].gen == from_space)) { - void *page_start, *addr; + void *page_start; page_start = (void *)page_address(i); @@ -5221,7 +5239,7 @@ print_ptr(lispobj *addr) if (pi1 != -1) fprintf(stderr," %x: page %d alloc %d gen %d bytes_used %d offset %d dont_move %d\n", - addr, + (unsigned int) addr, pi1, page_table[pi1].allocated, page_table[pi1].gen, @@ -5243,12 +5261,12 @@ print_ptr(lispobj *addr) extern int undefined_tramp; static void -verify_space(lispobj*start, size_t words) +verify_space(lispobj *start, size_t words) { - int dynamic_space = (find_page_index((void*)start) != -1); - int readonly_space = - (READ_ONLY_SPACE_START <= (int)start && - (int)start < SymbolValue(READ_ONLY_SPACE_FREE_POINTER)); + int is_in_dynamic_space = (find_page_index((void*)start) != -1); + int is_in_readonly_space = + (READ_ONLY_SPACE_START <= (unsigned)start && + (unsigned)start < SymbolValue(READ_ONLY_SPACE_FREE_POINTER)); while (words > 0) { size_t count = 1; @@ -5260,7 +5278,7 @@ verify_space(lispobj*start, size_t words) (READ_ONLY_SPACE_START <= thing && thing < SymbolValue(READ_ONLY_SPACE_FREE_POINTER)); int to_static_space = - ((int)static_space <= thing && + (STATIC_SPACE_START <= thing && thing < SymbolValue(STATIC_SPACE_FREE_POINTER)); /* Does it point to the dynamic space? */ @@ -5276,7 +5294,7 @@ verify_space(lispobj*start, size_t words) } /* Check that its not in the RO space as it would then be a * pointer from the RO to the dynamic space. */ - if (readonly_space) { + if (is_in_readonly_space) { lose("ptr to dynamic space %x from RO space %x", thing, start); } @@ -5289,7 +5307,7 @@ verify_space(lispobj*start, size_t words) } else { /* Verify that it points to another valid space. */ if (!to_readonly_space && !to_static_space - && (thing != (int)&undefined_tramp)) { + && (thing != (unsigned)&undefined_tramp)) { lose("Ptr %x @ %x sees junk.", thing, start); } } @@ -5334,7 +5352,7 @@ verify_space(lispobj*start, size_t words) /* Check that it's not in the dynamic space. * FIXME: Isn't is supposed to be OK for code * objects to be in the dynamic space these days? */ - if (dynamic_space + if (is_in_dynamic_space /* It's ok if it's byte compiled code. The trace * table offset will be a fixnum if it's x86 * compiled code - check. */ @@ -5435,19 +5453,25 @@ verify_space(lispobj*start, size_t words) static void verify_gc(void) { + /* FIXME: It would be nice to make names consistent so that + * foo_size meant size *in* *bytes* instead of size in some + * arbitrary units. (Yes, this caused a bug, how did you guess?:-) + * Some counts of lispobjs are called foo_count; it might be good + * to grep for all foo_size and rename the appropriate ones to + * foo_count. */ int read_only_space_size = (lispobj*)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) - (lispobj*)READ_ONLY_SPACE_START; int static_space_size = (lispobj*)SymbolValue(STATIC_SPACE_FREE_POINTER) - - (lispobj*)static_space; + - (lispobj*)STATIC_SPACE_START; int binding_stack_size = (lispobj*)SymbolValue(BINDING_STACK_POINTER) - (lispobj*)BINDING_STACK_START; verify_space((lispobj*)READ_ONLY_SPACE_START, read_only_space_size); - verify_space((lispobj*)static_space, static_space_size); - verify_space((lispobj*)BINDING_STACK_START, binding_stack_size); + verify_space((lispobj*)STATIC_SPACE_START , static_space_size); + verify_space((lispobj*)BINDING_STACK_START , binding_stack_size); } static void @@ -5508,7 +5532,7 @@ verify_zero_fill(void) } else { int free_bytes = 4096 - page_table[page].bytes_used; if (free_bytes > 0) { - int *start_addr = (int *)((int)page_address(page) + int *start_addr = (int *)((unsigned)page_address(page) + page_table[page].bytes_used); int size = free_bytes / 4; int i; @@ -5586,7 +5610,6 @@ write_protect_generation_pages(int generation) static void garbage_collect_generation(int generation, int raise) { - unsigned long allocated = bytes_allocated; unsigned long bytes_freed; unsigned long i; unsigned long read_only_space_size, static_space_size; @@ -5635,9 +5658,11 @@ garbage_collect_generation(int generation, int raise) /* Scavenge the stack's conservative roots. */ { lispobj **ptr; - for (ptr = (lispobj **)CONTROL_STACK_END-1; - ptr > (lispobj **)&raise; ptr--) + for (ptr = (lispobj **)CONTROL_STACK_END - 1; + ptr > (lispobj **)&raise; + ptr--) { preserve_pointer(*ptr); + } } #ifdef CONTROL_STACKS scavenge_thread_stacks(); @@ -5666,26 +5691,28 @@ garbage_collect_generation(int generation, int raise) } /* Scavenge the binding stack. */ - scavenge(binding_stack, - (lispobj *)SymbolValue(BINDING_STACK_POINTER) - binding_stack); + scavenge( (lispobj *) BINDING_STACK_START, + (lispobj *)SymbolValue(BINDING_STACK_POINTER) - + (lispobj *)BINDING_STACK_START); if (SymbolValue(SCAVENGE_READ_ONLY_SPACE) != NIL) { read_only_space_size = - (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) - - read_only_space; + (lispobj*)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) - + (lispobj*)READ_ONLY_SPACE_START; FSHOW((stderr, "/scavenge read only space: %d bytes\n", read_only_space_size * sizeof(lispobj))); - scavenge(read_only_space, read_only_space_size); + scavenge( (lispobj *) READ_ONLY_SPACE_START, read_only_space_size); } - static_space_size = (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER) - - static_space; + static_space_size = + (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER) - + (lispobj *)STATIC_SPACE_START; if (gencgc_verbose > 1) FSHOW((stderr, "/scavenge static space: %d bytes\n", static_space_size * sizeof(lispobj))); - scavenge(static_space, static_space_size); + scavenge( (lispobj *) STATIC_SPACE_START, static_space_size); /* All generations but the generation being GCed need to be * scavenged. The new_space generation needs special handling as @@ -5784,6 +5811,7 @@ update_x86_dynamic_space_free_pointer(void) SetSymbolValue(ALLOCATION_POINTER, (lispobj)(((char *)heap_base) + last_free_page*4096)); + return 0; /* dummy value: return something ... */ } /* GC all generations below last_gen, raising their objects to the @@ -5958,14 +5986,11 @@ gc_free_heap(void) addr); } } else if (gencgc_zero_check_during_free_heap) { - int *page_start, i; - /* Double-check that the page is zero filled. */ + int *page_start, i; gc_assert(page_table[page].allocated == FREE_PAGE); gc_assert(page_table[page].bytes_used == 0); - - page_start = (int *)page_address(i); - + page_start = (int *)page_address(page); for (i=0; i<1024; i++) { if (page_start[i] != 0) { lose("free region not zero at %x", page_start + i); @@ -6030,7 +6055,7 @@ gc_init(void) gc_init_tables(); - heap_base = (void*)DYNAMIC_0_SPACE_START; + heap_base = (void*)DYNAMIC_SPACE_START; /* Initialize each page structure. */ for (i = 0; i < NUM_PAGES; i++) { @@ -6089,7 +6114,7 @@ void gencgc_pickup_dynamic(void) { int page = 0; - int addr = DYNAMIC_0_SPACE_START; + int addr = DYNAMIC_SPACE_START; int alloc_ptr = SymbolValue(ALLOCATION_POINTER); /* Initialize the first region. */ @@ -6099,7 +6124,7 @@ gencgc_pickup_dynamic(void) page_table[page].bytes_used = 4096; page_table[page].large_object = 0; page_table[page].first_object_offset = - (void *)DYNAMIC_0_SPACE_START - page_address(page); + (void *)DYNAMIC_SPACE_START - page_address(page); addr += 4096; page++; } while (addr < alloc_ptr); @@ -6287,15 +6312,17 @@ clear_auto_gc_trigger(void) auto_gc_trigger = 0; } -/* Find the code object for the given pc, or return NULL on failure. */ -lispobj* +/* Find the code object for the given pc, or return NULL on failure. + * + * FIXME: PC shouldn't be lispobj*, should it? Maybe void*? */ +lispobj * component_ptr_from_pc(lispobj *pc) { lispobj *object = NULL; - if (object = search_read_only_space(pc)) + if ( (object = search_read_only_space(pc)) ) ; - else if (object = search_static_space(pc)) + else if ( (object = search_static_space(pc)) ) ; else object = search_dynamic_space(pc);