diff --git a/ldb/purify.c b/ldb/purify.c index 46b5d48408b1cb280455355c84e3372b1bab6987..bd7f49f0dabe81d6665db72aa4505abf3b3dbaf1 100644 --- a/ldb/purify.c +++ b/ldb/purify.c @@ -1,6 +1,6 @@ /* Purify. */ -/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/ldb/Attic/purify.c,v 1.5 1990/09/26 22:22:37 wlott Exp $ */ +/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/ldb/Attic/purify.c,v 1.6 1990/09/27 06:33:57 wlott Exp $ */ #include <mach.h> @@ -22,6 +22,19 @@ static lispobj *read_only_end, *static_end; static lispobj *read_only_free, *static_free; static lispobj *pscav(); +#define LATERBLOCKSIZE 1020 +#define LATERMAXCOUNT 10 + +static struct later { + struct later *next; + union { + lispobj *ptr; + int count; + } u[LATERBLOCKSIZE]; +} *later_blocks = NULL; +static int later_count = 0; + + #define NWORDS(x,y) (CEILING((x),(y)) / (y)) #define RAW_ADDR_OFFSET (6*sizeof(lispobj) - type_FunctionPointer) @@ -44,6 +57,35 @@ static boolean dynamic_pointer_p(ptr) return ptr >= (lispobj)dynamic_0_space; } +static void pscav_later(where, count) + lispobj *where; + int count; +{ + struct later *new; + + if (count > LATERMAXCOUNT) { + while (count > LATERMAXCOUNT) { + pscav_later(where, LATERMAXCOUNT); + count -= LATERMAXCOUNT; + where += LATERMAXCOUNT; + } + } + else { + if (later_blocks == NULL || later_count == LATERBLOCKSIZE || + (later_count == LATERBLOCKSIZE-1 && count > 1)) { + new = (struct later *)malloc(sizeof(struct later)); + new->next = later_blocks; + if (later_blocks && later_count < LATERBLOCKSIZE) + later_blocks->u[later_count].ptr = NULL; + later_blocks = new; + later_count = 0; + } + + if (count != 1) + later_blocks->u[later_count++].count = count; + later_blocks->u[later_count++].ptr = where; + } +} static lispobj ptrans_boxed(thing, header, constant) lispobj thing, header; @@ -193,18 +235,21 @@ static lispobj ptrans_code(thing) *(lispobj *)PTR(func) = result + (func - thing); } + /* Arrange to scavenge the debug info later. */ + pscav_later(&new->debug_info, 1); + /* Scavenge the constants. */ - pscav((lispobj *)new + 1, HeaderValue(new->header) - 1, TRUE); + pscav(new->constants, HeaderValue(new->header)-4, TRUE); /* Scavenge all the functions. */ + pscav(&new->entry_points, 1, TRUE); for (func = new->entry_points; func != NIL; func = ((struct function_header *)PTR(func))->next) { gc_assert(LowtagOf(func) == type_FunctionPointer); gc_assert(!dynamic_pointer_p(func)); - pscav((lispobj *)PTR(func) + 1, - (sizeof(struct function_header) / sizeof(lispobj)) - 1, - TRUE); + pscav(&((struct function_header *)PTR(func))->self, 2, TRUE); + pscav_later(&((struct function_header *)PTR(func))->name, 3); } return result; @@ -214,16 +259,36 @@ static lispobj ptrans_func(thing, header, constant) lispobj thing, header; boolean constant; { - lispobj code; + int nwords; + lispobj code, *new, *old, result; struct function_header *function; /* THING can either be a function header, a closure function header, or */ - /* a closure. If it's a closure, we just use ptrans_boxed, otherwise we */ - /* have to do something strange, 'cause it is buried inside a code */ - /* object. */ + /* a closure. If it's a closure, we do the same as ptrans_boxed, */ + /* otherwise we have to do something strange, 'cause it is buried inside */ + /* a code object. */ - if (TypeOf(header) == type_ClosureHeader) - return ptrans_boxed(thing, header, constant); + if (TypeOf(header) == type_ClosureHeader) { + nwords = 1 + HeaderValue(header); + + /* Allocate it. Closures can always go in read-only space, 'caues */ + /* they never change. */ + old = (lispobj *)PTR(thing); + new = read_only_free; + read_only_free += CEILING(nwords, 2); + + /* Copy it. */ + bcopy(old, new, nwords * sizeof(lispobj)); + + /* Deposit forwarding pointer. */ + result = (lispobj)new | LowtagOf(thing); + *old = result; + + /* Scavenge it. */ + pscav(new, nwords, constant); + + return result; + } else { gc_assert(TypeOf(header) == type_FunctionHeader || TypeOf(header) == type_ClosureFunctionHeader); @@ -398,6 +463,7 @@ static int pscav_symbol(symbol) return sizeof(struct symbol) / sizeof(lispobj); } +#if 0 static int pscav_code(addr) lispobj *addr; { @@ -405,10 +471,12 @@ static int pscav_code(addr) code = (struct code *)addr; - pscav(addr+1, HeaderValue(code->header)-1, TRUE); + pscav_later(&code->debug_info, 1); + pscav(code->constants, HeaderValue(code->header)-4, TRUE); return HeaderValue(code->header) + FIXNUM_TO_INT(code->code_size); } +#endif static lispobj *pscav(addr, nwords, constant) lispobj *addr; @@ -528,7 +596,10 @@ static lispobj *pscav(addr, nwords, constant) break; case type_CodeHeader: + gc_assert(0); /* No code headers in static space */ +#if 0 count = pscav_code(addr, thing); +#endif break; case type_FunctionHeader: @@ -563,10 +634,12 @@ static lispobj *pscav(addr, nwords, constant) } -int purify(roots) -lispobj roots; +int purify(static_roots, read_only_roots) +lispobj static_roots; { lispobj *clean; + int count, i; + struct later *laters, *next; #ifdef PRINTNOISE printf("[Doing purification:"); @@ -588,7 +661,8 @@ lispobj roots; printf(" roots"); fflush(stdout); #endif - pscav(&roots, 1, FALSE); + pscav(&static_roots, 1, FALSE); + pscav(&read_only_roots, 1, TRUE); #ifdef PRINTNOISE printf(" handlers"); @@ -615,8 +689,31 @@ lispobj roots; fflush(stdout); #endif clean = static_space; - while (clean != static_free) - clean = pscav(clean, static_free - clean, FALSE); + do { + while (clean != static_free) + clean = pscav(clean, static_free - clean, FALSE); + laters = later_blocks; + count = later_count; + later_blocks = NULL; + later_count = 0; + while (laters != NULL) { + for (i = 0; i < count; i++) { + if (laters->u[i].count == 0) + ; + else if (laters->u[i].count <= LATERMAXCOUNT) { + pscav(laters->u[i+1].ptr, laters->u[i].count, TRUE); + i++; + } + else + pscav(laters->u[i].ptr, 1, TRUE); + } + next = laters->next; + free(laters); + laters = next; + count = LATERBLOCKSIZE; + } + } while (clean != static_free || later_blocks != NULL); + #ifdef PRINTNOISE printf(" cleanup");