1 /* cgc.c -*- Mode: C; comment-column: 40; -*-
2 * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/cgc.c,v 1.14 2008/03/19 09:17:10 cshapiro Rel $
4 * Conservative Garbage Collector for CMUCL x86.
6 * This code is based on software written by William Lott, and
7 * Public Domain codes from Carnegie Mellon University, and has
8 * been placed in the Public Domain.
10 * Received from William 27 Jul 95.
12 * Debug, FreeBSD hooks, and integration by Paul Werkowski
20 #include "os.h" /* for SetSymbolValue */
21 #include "globals.h" /* For dynamic_space_size */
22 #include "x86-validate.h" /* for memory layout */
23 #include "x86-lispregs.h"
24 #include "lisp.h" /* for object defs */
25 #include "interrupt.h" /* interrupt_handlers */
26 #include "internals.h"
30 #define MIN(a,b)(((a)<(b))?(a):(b))
31 #define MAX(a,b)(((a)>(b))?(a):(b))
37 #include <sys/param.h>
39 #include <sys/types.h>
41 #include <sys/resource.h>
44 #define dprintf(t,exp) if(t){printf exp ; fflush(stdout);}
46 /* Object representation details. The allocator/collector knows
47 * almost nothing about lisp internals and is fairly general.
51 #define ALIGN_BYTES (1<<ALIGN_BITS)
52 #define ALIGNEDP(addr) ((((int)addr)&(ALIGN_BYTES-1)) == 0)
54 /* Type of an object. */
55 typedef struct object {
57 struct object *data[1];
60 /* Just leave unused space */
61 #define NOTE_EMPTY(ptr,bytes) {}
64 /* Collector datastructures */
67 #define BLOCK_BYTES (1<<BLOCK_BITS)
68 #define BLOCK_NUMBER(ptr) (((long)(ptr))>>BLOCK_BITS)
69 #define BLOCK_ADDRESS(num) ((void *)((num)<<BLOCK_BITS))
72 #define CHUNK_BYTES (1<<CHUNK_BITS)
73 #define CHUNK_NUMBER(ptr) (((long)(ptr))>>CHUNK_BITS)
74 #define CHUNK_ADDRESS(num) ((void *)((num)<<CHUNK_BITS))
76 #define BLOCK_CHUNKS (1<<(BLOCK_BITS-CHUNK_BITS))
79 #define ROUNDDOWN(val,x) ((val)&~((x)-1))
80 #define ROUNDUP(val,x) ROUNDDOWN((val)+(x)-1,x)
82 #define gc_abort() lose("GC invariant lost! File \"%s\", line %d\n", \
86 #define gc_assert(ex) {if (!(ex)) gc_abort();}
95 /* Link to the next cluster. */
98 /* The number of blocks in this cluster. */
101 /* Pointer to the first region. */
102 struct region *first_region;
104 /* Table index by the chunk number of some pointer minus the chunk */
105 /* number for the first region giving the number of chunks past */
106 /* the chunk holding the region header that spans that pointer. */
107 /* Actually, it might not be enough. So after backing up that far, */
109 unsigned char region_offset[1];
112 /* The first word of this is arranged to look like a fixnum
113 * so as not to confuse 'room'.
117 res1:2, num_chunks:16, contains_small_objects:1, clean:1, hole:7;
118 struct region **prev;
123 #define REGION_OVERHEAD ROUNDUP(sizeof(struct region), ALIGN_BYTES)
127 struct region *regions;
128 struct region **regions_tail;
133 /* Chain of all the clusters. */
134 struct cluster *clusters = NULL;
135 static int num_clusters = 0; /* for debugging */
136 int cgc_debug = 0; /* maybe set from Lisp */
138 /* Table indexed by block number giving the cluster that block is part of. */
139 static struct cluster **block_table = NULL;
141 /* The allocated memory block_table is offset from. */
142 static struct cluster **block_table_base = NULL;
144 /* The maximum bounds on the heap. */
145 static void *heap_base = NULL;
146 static void *heap_end = NULL;
148 /* The two dynamic spaces. */
149 static struct space space_0 = { NULL };
150 static struct space space_1 = { NULL };
152 /* Pointers it whichever dynamic space is currently newspace and oldspace */
153 static struct space *newspace = NULL;
154 static struct space *oldspace = NULL;
156 /* Free lists of regions. */
157 static struct region *small_region_free_list = NULL;
158 static struct region *large_region_free_list = NULL;
159 static void move_to_newspace(struct region *region);
163 print_region(struct region *r)
165 dprintf(1, ("[region %x %d <%x %x> %x]\n",
166 r, r->num_chunks, r->prev, r->next, r->space));
169 print_regions(struct region *r, char *str)
171 printf("Regions %s:\n", str);
172 for (; r != NULL; r = r->next)
177 print_space(struct space *s)
179 struct region *r = s->regions;
181 dprintf(1, ("[space %x %s %s <%x - %x>]\n",
183 (s == &space_0) ? "S0" : "S1",
184 (s == newspace) ? "NewSpace" : "OldSpace",
185 s->alloc_ptr, s->alloc_end));
186 print_regions(r, "");
193 print_space(&space_0);
194 print_space(&space_1);
195 print_regions(large_region_free_list, "LRFL");
196 print_regions(small_region_free_list, "SRFL");
200 print_cluster(struct cluster *cluster)
202 printf("[cluster %x >%x %d]\n", cluster, cluster->next,
203 cluster->num_blocks);
204 print_regions(cluster->first_region, "cluster");
210 struct cluster *cluster;
212 for (cluster = clusters; cluster != NULL; cluster = cluster->next)
213 print_cluster(cluster);
218 /* Allocation/deallocation routines */
221 init_region(struct region *region, int nchunks)
223 int region_block = BLOCK_NUMBER(region);
224 struct cluster *cluster = block_table[region_block];
225 int offset = CHUNK_NUMBER(region) - CHUNK_NUMBER(cluster->first_region);
228 dprintf(0, ("init region %x %d\n", region, nchunks));
229 *(long *) region = 0; /* clear fields */
230 region->num_chunks = nchunks;
231 if (nchunks > UCHAR_MAX) {
232 for (i = 0; i < UCHAR_MAX; i++)
233 cluster->region_offset[offset + i] = i;
234 for (; i < nchunks; i++)
235 cluster->region_offset[offset + i] = UCHAR_MAX;
237 for (i = 0; i < nchunks; i++)
238 cluster->region_offset[offset + i] = i;
242 static struct region *
243 maybe_alloc_large_region(int nchunks)
245 struct region *region, **prev;
247 prev = &large_region_free_list;
248 while ((region = *prev) != NULL) {
249 if (region->num_chunks >= nchunks) {
250 if (region->num_chunks == nchunks)
251 *prev = region->next;
256 (struct region *) ((char *) region + nchunks * CHUNK_BYTES);
257 init_region(new, region->num_chunks - nchunks);
258 new->next = region->next;
262 region->num_chunks = nchunks;
266 region->space = NULL;
269 prev = ®ion->next;
277 cgc_zero(addr, length)
278 os_vm_address_t addr;
281 os_vm_address_t block_start = os_round_up_to_page(addr);
282 os_vm_address_t end = addr + length;
283 os_vm_size_t block_size;
286 if (block_start > addr)
287 memset((char *) addr, 0, MIN(block_start - addr, length))
289 if (block_start < end) {
290 length -= block_start - addr;
292 block_size = os_trunc_size_to_page(length);
294 if (block_size < length)
295 memset((char *) block_start + block_size, 0,
296 length - block_size);
298 if (block_size != 0) {
299 /* Now deallocate and allocate the block so that it */
300 /* faults in zero-filled. */
302 os_invalidate(block_start, block_size);
303 addr = os_validate(block_start, block_size);
305 if (addr == NULL || addr != block_start)
307 "cgc_zero: block moved, 0x%08x ==> 0x%08x!\n",
314 compact_cluster(struct cluster *cluster)
317 struct region *region = cluster->first_region;
319 (struct region *) ((char *) region + cluster->num_blocks * BLOCK_BYTES);
321 unsigned max_chunks = cluster->num_blocks * BLOCK_CHUNKS;
322 struct region *large_additions = NULL;
323 struct region **large_prev = &large_additions;
324 struct region *small_additions = NULL;
325 struct region **small_prev = &small_additions;
327 dprintf(show, ("compact cluster %x\n", cluster));
328 while (region < end) {
329 struct region *next =
330 (struct region *) ((char *) region +
332 region->num_chunks * CHUNK_BYTES);
333 if (region->space != newspace) { /* was == NULL */
334 if (next < end && next->space != newspace) { /* was == NULL */
335 gc_assert(region >= cluster->first_region);
336 gc_assert(region->space == NULL);
337 gc_assert(next->space == NULL);
338 gc_assert(region->num_chunks > 0);
339 gc_assert(next->num_chunks > 0);
340 gc_assert((region->num_chunks + next->num_chunks) <=
342 region->num_chunks += next->num_chunks;
346 init_region(region, region->num_chunks);
347 region->space = NULL;
351 int ovh = REGION_OVERHEAD;
353 cgc_zero((os_vm_address_t) ((char *) region + ovh),
354 (os_vm_size_t) (region->num_chunks * CHUNK_BYTES) -
358 if (region->num_chunks == 1) {
359 *small_prev = region;
360 small_prev = ®ion->next;
362 *large_prev = region;
363 large_prev = ®ion->next;
371 *large_prev = large_region_free_list;
372 large_region_free_list = large_additions;
373 *small_prev = small_region_free_list;
374 small_region_free_list = small_additions;
378 compact_free_regions(void)
380 struct cluster *cluster;
382 large_region_free_list = NULL;
383 small_region_free_list = NULL;
385 for (cluster = clusters; cluster != NULL; cluster = cluster->next)
386 compact_cluster(cluster);
389 /* WL code arranged to allocate new space via the sbrk() mechanism.
390 * However, I am going to start by allocating from the standard dynamic
391 * space. The idea is to use the normal allocation scheme for initial
392 * system build and switch to the cgc allocator when starting up a
393 * saved image when dynamic space is hopefully clean.
395 static struct region *
396 new_region(int nblocks)
398 /* take from existing dynamic space */
399 char *new = (char *) SymbolValue(ALLOCATION_POINTER);
400 struct region *region =
402 (struct region *) (ROUNDUP((long) new, BLOCK_BYTES));
403 int bn = BLOCK_NUMBER(region);
405 new += (nblocks * BLOCK_BYTES + ((char *) region - new));
406 SetSymbolValue(ALLOCATION_POINTER, (lispobj) new);
411 new_cluster(int min_blocks)
413 int nblocks = min_blocks < 4 ? 4 : min_blocks;
414 int nchunks = nblocks << (BLOCK_BITS - CHUNK_BITS);
416 struct cluster *cluster = malloc(sizeof(struct cluster) + nchunks - 1);
417 struct region *region = new_region(nblocks);
419 int bn = BLOCK_NUMBER(region);
421 dprintf(cgc_debug, ("new cluster %x region@%x\n", cluster, region));
422 for (i = 0; i < nblocks; i++)
423 block_table[bn + i] = cluster;
426 cluster->next = clusters;
428 cluster->num_blocks = nblocks;
429 cluster->first_region = region;
431 init_region(region, nchunks);
433 region->next = large_region_free_list;
434 large_region_free_list = region;
436 region->space = NULL;
439 unsigned long bytes_allocated = 0; /* Seen by (dynamic-usage) */
440 static unsigned long auto_gc_trigger = 0;
441 static int maybe_gc_called = 0;
443 static struct region *
444 alloc_large_region(int nchunks)
446 struct region *region;
449 region = maybe_alloc_large_region(nchunks);
451 if (region == NULL) {
452 new_cluster((nchunks + BLOCK_CHUNKS - 1) >>
453 (BLOCK_BITS - CHUNK_BITS));
454 region = maybe_alloc_large_region(nchunks);
455 gc_assert(region != NULL);
458 gc_assert(region->space == NULL);
462 static struct region *
463 alloc_small_region(void)
465 struct region *region = small_region_free_list;
468 region = alloc_large_region(1);
470 small_region_free_list = region->next;
473 region->space = NULL;
474 move_to_newspace(region);
478 static int chunks_freed = 0;
481 free_region(struct region *region)
483 gc_assert(region->space && region->space == oldspace);
484 gc_assert(region->num_chunks > 0);
486 region->space = NULL; /* for compact_cluster? */
487 region->prev = NULL; /* housekeeping I hope */
488 chunks_freed += region->num_chunks;
490 if (region->num_chunks == 1) {
491 region->next = small_region_free_list;
492 small_region_free_list = region;
494 region->next = large_region_free_list;
495 large_region_free_list = region;
500 alloc_large(int nbytes)
502 int nchunks = (nbytes + REGION_OVERHEAD + CHUNK_BYTES - 1) >> CHUNK_BITS;
503 struct region *region = alloc_large_region(nchunks);
505 region->contains_small_objects = 0;
508 region->space = NULL;
509 bytes_allocated += region->num_chunks * CHUNK_BYTES;
510 move_to_newspace(region);
511 return (char *) region + REGION_OVERHEAD;
515 cgc_alloc(int nbytes)
519 dprintf(0, ("alloc %d\n", nbytes));
521 if (nbytes > (CHUNK_BYTES - REGION_OVERHEAD))
522 res = alloc_large(nbytes);
524 struct space *space = newspace;
526 if ((space->alloc_ptr + nbytes) > space->alloc_end) {
527 struct region *region;
529 if (space->alloc_ptr != NULL) {
530 int hole = space->alloc_end - space->alloc_ptr;
532 if (hole >= ALIGN_BYTES)
533 /* This wastes the space, eg suppose one cons
534 * has been allocated then a request for
535 * a maximum sized small obj comes in. I'd like
536 * to remember that there is still a lot of
537 * room left in this region. Maybe I could actually
538 * use the small_region_free_list in some way.
540 NOTE_EMPTY(space->alloc_ptr, hole);
542 region = alloc_small_region();
543 region->contains_small_objects = 1;
544 space->alloc_ptr = (char *) region + REGION_OVERHEAD;
545 space->alloc_end = (char *) region + CHUNK_BYTES;
546 bytes_allocated += region->num_chunks * CHUNK_BYTES;
549 res = space->alloc_ptr;
550 space->alloc_ptr += ROUNDUP(nbytes, ALIGN_BYTES);
557 move_to_newspace(struct region *region)
559 /* (maybe) unlink region from oldspace and add to tail of
560 * newspace regions. Don't attempt to move a region that
561 * is already in newspace.
563 struct space *space = newspace;
565 if (region->space == oldspace) {
566 /* Remove region from list. The prev slot holds
567 * the address of the 'next' slot of the previous
568 * list entry, not a pointer to that region (why?)
570 *region->prev = region->next;
572 region->next->prev = region->prev;
573 if (region->space->regions_tail == ®ion->next)
574 region->space->regions_tail = region->prev;
576 /* Append to newspace unless it has already been promoted. */
577 if (region->space != newspace) {
578 region->prev = space->regions_tail;
580 *space->regions_tail = region;
581 space->regions_tail = ®ion->next;
582 region->space = space;
586 static struct region *
587 find_region(void *ptr)
589 struct cluster *cluster;
590 int cluster_chunk_num;
594 ptr = (void *) ((int) ptr & ~0x3);
595 if (ptr < heap_base || ptr >= heap_end)
598 cluster = block_table[BLOCK_NUMBER(ptr)];
602 if (ptr < (void *) cluster->first_region)
605 cluster_chunk_num = CHUNK_NUMBER(cluster->first_region);
606 chunk_num = CHUNK_NUMBER(ptr);
608 while (delta = cluster->region_offset[chunk_num - cluster_chunk_num])
611 return CHUNK_ADDRESS(chunk_num);
614 /* Interface to std collector */
615 static inline boolean
616 from_space_p(lispobj obj)
618 struct region *region = find_region((void *) obj);
620 return (region != NULL && region->space == oldspace);
622 static inline boolean
623 new_space_p(lispobj obj)
625 struct region *region = find_region((void *) obj);
627 return (region != NULL && region->space == newspace);
629 static inline boolean
630 static_space_p(lispobj obj)
632 return (STATIC_SPACE_START < obj
633 && obj < SymbolValue(STATIC_SPACE_FREE_POINTER));
636 /* Predicate that returns true if an object is a pointer. */
638 #define POINTERP(obj) Pointerp((obj)->header)
640 /* Predicate that returns true if an object has been forwarded. */
641 #define FORWARDED(obj) ((obj_t)(obj)->header == (obj_t)0x1)
643 /* Returns the forwarding pointer for the given object. */
644 #define FORWARDING_PTR(obj) ((lispobj)(obj)->data[0])
646 /* Marks obj as forwarded to new */
647 #define DEPOSIT_FORWARDING_PTR(obj,new) \
648 ((obj_t)(obj)->header = 0x1, (obj_t)(obj)->data[0] = (obj_t)new)
650 /* Returns an obj_t for the object starting at addr */
651 #define OBJECT_AT(addr) ((obj_t)(addr))
653 /* Returns the size (in bytes) of obj. */
654 #define OBJECT_SIZE(obj) (sizeOfObject((obj_t)obj)<<2)
656 /* Scavenges an object. */
657 #define SCAVENGE_OBJECT(obj) scavengex((lispobj*)obj)
660 /* Makes a region of memory look like some kind of object. */
661 #define NOTE_EMPTY(ptr,bytes) \
662 (((obj_t)ptr)->header = (((bytes+ALIGN_BYTES-1)>>ALIGN_BITS)<<8) | 1)
665 static unsigned long bytes_copied = 0;
667 # define HAVE_FASTCOPY
668 #if defined HAVE_FASTCOPY
669 #define COPYDUAL(a,b,c) fastcopy16(a,b,c)
670 void fastcopy16(void *, void *, size_t);
672 #define COPYDUAL(a,b,c) memmove(a,b,c)
674 static inline lispobj
675 copy(lispobj taggedobj)
677 obj_t source = (obj_t) PTR(taggedobj);
678 int nbytes = OBJECT_SIZE(source);
680 gc_assert(Pointerp(taggedobj));
681 gc_assert(!(nbytes & (ALIGN_BYTES - 1)));
683 int lowtag = LowtagOf(taggedobj);
684 obj_t newobj = cgc_alloc(nbytes);
686 COPYDUAL(newobj, source, nbytes);
687 bytes_copied += nbytes;
688 return ((lispobj) newobj | lowtag);
693 #define CEILING(x,y) (((x) + ((y) - 1)) & (~((y) - 1)))
694 #define NWORDS(x,y) (CEILING((x),(y)) / (y))
696 #define WEAK_POINTER_NWORDS \
697 CEILING((sizeof(struct weak_pointer) / sizeof(lispobj)), 2)
698 static struct weak_pointer *weak_pointers;
702 * CMU CL objects can be classified as BOXED, UNBOXED or other.
703 * Boxed objects have a header containing length and type followed
704 * by LENGTH tagged object descriptors which may be pointers.
705 * UNBOXED objects have a header but the data is other than
706 * tagged descriptors, such as floats, bignums, saps or code.
707 * Others (code) contain a mix of boxed and unboxed and some
708 * (cons) are like BOXED but without header. The scavenger needs
709 * to consider these different kinds of objects. I will use a
710 * table indexed by type to detect the simple cases of boxed
713 #define IMMED_OR_LOSE(thing) gc_assert(sct[TypeOf(thing)].sc_kind == SC_IMMED)
714 static void scavenge_pointer(lispobj *);
715 static int noise = 0;
718 unsigned sc_kind:3, ve_l2bits:5;
722 make_OSC(int kind, int log2bits)
726 thing.sc_kind = kind;
727 thing.ve_l2bits = log2bits;
731 #define SETSCT(indx,kind,logbits) sct[indx] = make_OSC(kind,logbits)
740 static OSC_t sct[256];
743 sizeOfObject(obj_t obj)
745 int obj_type = TypeOf(obj->header);
746 OSC_t class = sct[obj_type];
747 struct vector *vector;
751 switch (class.sc_kind) {
757 gc_assert(HeaderValue(obj->header) > 0);
758 nwords = length = HeaderValue(obj->header) + 1;
763 int log2bits = class.ve_l2bits;
764 int bits_per_el = 1 << log2bits;
766 int els_per_word = 1 << (5 - log2bits);
770 extra = log2bits - 5;
772 length = ((struct vector *) obj)->length;
773 length = fixnum_value(length); /* Zero Length IS valid */
774 length += (class.sc_kind == SC_STRING);
776 nwords = NWORDS(length, els_per_word);
777 nwords += 2; /* header + length */
782 case type_CodeHeader:
785 int nheader_words, ncode_words;
787 code = (struct code *) obj;
788 ncode_words = fixnum_value(code->code_size);
789 nheader_words = HeaderValue(code->header);
790 nwords = ncode_words + nheader_words;
793 fprintf(stderr, "GC losage: no size for other type %d\n",
799 fprintf(stderr, "GC losage: no size for other type %d\n", obj_type);
802 return CEILING(nwords, 2);
810 for (i = 0; i < 256; i++)
811 SETSCT(i, SC_LOSER, 0);
812 for (i = 0; i < 32; i++) {
813 SETSCT(type_EvenFixnum | (i << 3), SC_IMMED, 0);
814 SETSCT(type_FunctionPointer | (i << 3), SC_POINTER, 0);
815 /* OtherImmediate0 */
816 SETSCT(type_ListPointer | (i << 3), SC_POINTER, 0);
817 SETSCT(type_OddFixnum | (i << 3), SC_IMMED, 0);
818 SETSCT(type_InstancePointer | (i << 3), SC_POINTER, 0);
819 /* OtherImmediate1 */
820 SETSCT(type_OtherPointer | (i << 3), SC_POINTER, 0);
822 SETSCT(type_Bignum, SC_UNBOXED, 0);
823 SETSCT(type_Ratio, SC_ISBOXED, 0);
824 SETSCT(type_SingleFloat, SC_UNBOXED, 0);
825 SETSCT(type_DoubleFloat, SC_UNBOXED, 0);
826 #if defined type_ComplexSingleFloat
827 SETSCT(type_ComplexSingleFloat, SC_UNBOXED, 0);
829 #if defined type_ComplexDoubleFloat
830 SETSCT(type_ComplexDoubleFloat, SC_UNBOXED, 0);
832 SETSCT(type_Complex, SC_ISBOXED, 0);
833 SETSCT(type_SimpleArray, SC_ISBOXED, 0);
834 SETSCT(type_SimpleString, SC_STRING, 3);
835 SETSCT(type_SimpleBitVector, SC_VECTOR, 0);
836 SETSCT(type_SimpleVector, SC_VECTOR, 5);
837 SETSCT(type_SimpleArrayUnsignedByte2, SC_VECTOR, 1);
838 SETSCT(type_SimpleArrayUnsignedByte4, SC_VECTOR, 2);
839 SETSCT(type_SimpleArrayUnsignedByte8, SC_VECTOR, 3);
840 SETSCT(type_SimpleArrayUnsignedByte16, SC_VECTOR, 4);
841 SETSCT(type_SimpleArrayUnsignedByte32, SC_VECTOR, 5);
842 #if defined type_SimpleArraySignedByte8
843 SETSCT(type_SimpleArraySignedByte8, SC_VECTOR, 3);
845 #if defined type_SimpleArraySignedByte16
846 SETSCT(type_SimpleArraySignedByte16, SC_VECTOR, 4);
848 #if defined type_SimpleArraySignedByte30
849 SETSCT(type_SimpleArraySignedByte30, SC_VECTOR, 5);
851 #if defined type_SimpleArraySignedByte32
852 SETSCT(type_SimpleArraySignedByte32, SC_VECTOR, 5);
854 SETSCT(type_SimpleArraySingleFloat, SC_VECTOR, 5);
855 SETSCT(type_SimpleArrayDoubleFloat, SC_VECTOR, 6);
856 #if defined type_SimpleArrayComplexSingleFloat
857 SETSCT(type_SimpleArrayComplexSingleFloat, SC_VECTOR, 6);
859 #if defined type_SimpleArrayComplexDoubleFloat
860 SETSCT(type_SimpleArrayComplexDoubleFloat, SC_VECTOR, 7);
862 SETSCT(type_ComplexString, SC_ISBOXED, 0);
863 SETSCT(type_ComplexBitVector, SC_ISBOXED, 0);
864 SETSCT(type_ComplexVector, SC_ISBOXED, 0);
865 SETSCT(type_ComplexArray, SC_ISBOXED, 0);
866 SETSCT(type_CodeHeader, SC_OTHER, 0);
867 SETSCT(type_FunctionHeader, SC_OTHER, 0);
868 SETSCT(type_ClosureFunctionHeader, SC_OTHER, 0);
869 SETSCT(type_ReturnPcHeader, SC_OTHER, 0);
870 SETSCT(type_ClosureHeader, SC_ISBOXED, 0);
871 SETSCT(type_FuncallableInstanceHeader, SC_ISBOXED, 0);
872 SETSCT(type_ByteCodeFunction, SC_ISBOXED, 0);
873 SETSCT(type_ByteCodeClosure, SC_ISBOXED, 0);
874 SETSCT(type_DylanFunctionHeader, SC_ISBOXED, 0);
876 SETSCT(type_ValueCellHeader, SC_ISBOXED, 0);
877 SETSCT(type_SymbolHeader, SC_ISBOXED, 0);
878 SETSCT(type_BaseChar, SC_IMMED, 0);
879 SETSCT(type_Sap, SC_UNBOXED, 0);
880 SETSCT(type_UnboundMarker, SC_IMMED, 0);
881 SETSCT(type_WeakPointer, SC_UNBOXED, 0);
882 SETSCT(type_InstanceHeader, SC_ISBOXED, 0);
883 SETSCT(type_Fdefn, SC_ISBOXED, 0);
886 static lispobj *scavenge(lispobj *, int);
887 static lispobj *scavenge_object(lispobj *);
888 static lispobj *scavengex(lispobj *);
891 scavenge_1word_obj(lispobj * addr)
893 if (Pointerp(*addr)) {
894 if (*addr != NIL && *addr != T)
895 scavenge_pointer(addr);
897 IMMED_OR_LOSE(*addr);
899 static int debug_code = 0;
901 scav_code_header(lispobj * where)
903 lispobj object = *where;
905 int i, nheader_words, ncode_words, nwords;
907 struct function *fheaderp;
909 dprintf(0, ("code: %x %x\n", where, object));
910 code = (struct code *) where;
911 ncode_words = fixnum_value(code->code_size);
912 nheader_words = HeaderValue(object);
913 nwords = ncode_words + nheader_words;
914 nwords = CEILING(nwords, 2);
915 /* Scavenge the boxed section of the code data block */
916 /* NOTE: seeing a problem where the trace_table_offset slot
917 * is a bogus list pointer instead of a fixnum such that
918 * junk gets moved to newspace which causes problems later.
919 * Purify doesn't look at that slot (a bug?). Need
920 * to figure out how it happens. Ans: from loading top-level
921 * forms that init byte-compiled functions like "defun fcn".
922 * Fix the loader to not do this and save some space!
924 for (i = 1; i < nheader_words; i++)
925 scavenge_1word_obj(where + i);
927 /* Scavenge the boxed section of each function object in the
930 fheaderl = code->entry_points;
931 while (fheaderl != NIL) {
932 fheaderp = (struct function *) PTR(fheaderl);
933 gc_assert(TypeOf(fheaderp->header) == type_FunctionHeader);
934 scavenge_1word_obj(&fheaderp->name);
935 scavenge_1word_obj(&fheaderp->arglist);
936 scavenge_1word_obj(&fheaderp->type);
937 fheaderl = fheaderp->next;
942 #define RAW_ADDR_OFFSET (6*sizeof(lispobj) - type_FunctionPointer)
945 scavenge_fcn_header(struct function *object)
947 struct function *fheader = object;
948 unsigned long offset = HeaderValue(fheader->header) * 4;
950 /* Ok, we don't transport code here, but we do need to
951 * scavenge the constants and functions (of which this is one).
952 * This should be done as part of scavenging a live code object
953 * and we could now be trying to do CPR on a corpse!
955 struct code *code = (struct code *) ((unsigned long) fheader - offset);
957 gc_assert(TypeOf(fheader->header) == type_FunctionHeader);
958 scav_code_header((lispobj *) code);
961 static int docode = 0; /* maybe not needed */
963 scav_closure_header(struct closure *closure)
965 /* Could also be a funcallable_instance. The x86 port has the
966 * raw code address in the function slot, not a lisp object.
967 * However, the function object is a known distance from the code.
969 lispobj fun, fheader1;
972 gc_assert(ALIGNEDP(closure));
973 words = HeaderValue(closure->header);
974 fun = closure->function - RAW_ADDR_OFFSET;
975 /* This needs to be done to get at live code. I now have no
976 * way to know if this has already been scavenged so I assume
977 * that it hasn't. Code that has been seen by purify is
978 * supposed RO and doesn't (shouldn't) need to be looked at
979 * so this maybe really redundant.
981 * I have seen one case where FI was incomplete with function
982 * and lexenv slots == 0! Is this a bug?
984 * Update, it appears this is not needed. I will disable execution
985 * by default but leave the code here in case something breaks.
987 if (docode && static_space_p(closure->function))
988 scavenge_fcn_header((struct function *) PTR(fun));
990 scavenge_1word_obj(&fun);
992 /* Now the boxed part of the closure header. */
993 for (i = 0; i < words - 1; i++)
994 scavenge_1word_obj(&closure->info[i]);
996 return CEILING(words + 1, 2);
998 static int fnoise = 0; /* experimental */
1000 scav_fdefn(lispobj * where)
1002 /* I don't know if this is really needs to be special cased here.
1003 * raw_address should look like a fixnum and function is in static
1004 * space -- unless it is pointing to something in C like closure_tramp
1005 * or maybe undefined_tramp.
1006 * Actually function is in dynamic space if it is a byte-function!
1007 * Hmm, have seen case of function slot containing 1. Bug?
1009 struct fdefn *fdefn = (struct fdefn *) where;
1010 int words = HeaderValue(fdefn->header);
1013 ((char *) (fdefn->function + RAW_ADDR_OFFSET) == fdefn->raw_addr);
1014 scavenge_pointer(&fdefn->name);
1015 if (fnoise && LowtagOf(fdefn->function) == type_FunctionPointer) {
1016 obj_t fcnobj = (obj_t) PTR(fdefn->function);
1018 switch (TypeOf(fcnobj->header)) {
1019 /* Can only be in static space and may need to scavenge code object.
1020 * Won't be noticed by scavenge_pointer().
1022 case type_FunctionHeader:
1023 scavenge_fcn_header((struct function *) fcnobj);
1025 /* If in static space it was moved there by purify and we are
1026 * doing normal scavenge. Handle normally.
1028 case type_FuncallableInstanceHeader:
1029 case type_ClosureHeader:
1030 scavenge_pointer(&fdefn->function);
1033 dprintf(1, ("Ignoring bogus value %x for fdefn function.\n",
1037 /* NIL for undefined function? */
1038 scavenge_pointer(&fdefn->function);
1040 if (fix_func) { /* This shouldn't be needed yet. */
1041 fdefn->raw_addr = (char *) (fdefn->function + RAW_ADDR_OFFSET);
1043 return sizeof(struct fdefn) / sizeof(lispobj);
1048 /* List scavenger taken from gc.c and adapted */
1050 static FILE *log = NULL;
1051 static int scav_ro = 0; /* for testing */
1052 static int debug = 0;
1053 static void *trapaddr = 0;
1055 check_trap(void *addr)
1057 fprintf(stderr, "Trapped @ %x\n", addr);
1061 trans_list(lispobj object)
1063 lispobj new_list_pointer;
1064 struct cons *cons, *new_cons;
1068 cons = (struct cons *) PTR(object);
1071 new_cons = (struct cons *) cgc_alloc(sizeof(struct cons));
1073 new_cons->car = cons->car;
1074 new_cons->cdr = cons->cdr; /* updated later */
1075 new_list_pointer = (lispobj) new_cons | LowtagOf(object);
1076 bytes_copied += sizeof(struct cons);
1082 fprintf(log, "( %d cons @ #x%x -> #x%x car #x%x)\n",
1083 n++, cons, new_cons, new_cons->car);
1085 /* Grab the cdr before it is clobbered */
1087 /* Set forwarding pointer (clobbers start of list). */
1088 DEPOSIT_FORWARDING_PTR((obj_t) cons, new_list_pointer);
1090 /* Try to linearize the list in the cdr direction to help reduce paging. */
1093 struct cons *cdr_cons, *new_cdr_cons;
1095 if (LowtagOf(cdr) != type_ListPointer || !from_space_p(cdr)
1096 || FORWARDED((obj_t) PTR(cdr)))
1099 cdr_cons = (struct cons *) PTR(cdr);
1102 new_cdr_cons = (struct cons *) cgc_alloc(sizeof(struct cons));
1104 new_cdr_cons->car = cdr_cons->car;
1105 new_cdr_cons->cdr = cdr_cons->cdr;
1106 new_cdr = (lispobj) new_cdr_cons | LowtagOf(cdr);
1107 bytes_copied += sizeof(struct cons);
1113 fprintf(log, "( %d cons @ #x%x -> #x%x car #x%x)\n",
1114 n++, cdr_cons, new_cdr_cons, cdr_cons->car);
1116 /* Grab the cdr before it is clobbered */
1117 cdr = cdr_cons->cdr;
1118 /* Set forwarding pointer */
1119 DEPOSIT_FORWARDING_PTR((obj_t) cdr_cons, new_cdr);
1121 /* Update the cdr of the last cons copied into new
1122 * space to keep the newspace scavenge from having to do it.
1124 new_cons->cdr = new_cdr;
1126 new_cons = new_cdr_cons;
1129 return new_list_pointer;
1133 static int weak_noise = 0;
1134 static int do_weak = 1;
1136 scav_weak_pointer(lispobj * where)
1138 struct weak_pointer *wp = weak_pointers;
1140 /* Push the weak pointer onto the list of weak pointers.
1141 * Do I have to watch for duplicates? Originally this was
1142 * part of trans_weak_pointer but that didn't work in the
1143 * case where the WP was in a promoted region.
1146 while (wp != NULL) {
1147 if (wp == (struct weak_pointer *) where)
1152 wp = (struct weak_pointer *) where;
1153 wp->next = weak_pointers;
1156 scavenge_1word_obj(&wp->value);
1159 /* Do not let GC scavenge the value slot of the weak pointer
1160 * (that is why it is a weak pointer).
1163 return WEAK_POINTER_NWORDS;
1167 scan_weak_pointers(void)
1169 struct weak_pointer *wp;
1171 for (wp = weak_pointers; wp != NULL; wp = wp->next) {
1172 lispobj value = wp->value;
1173 obj_t obj = (obj_t) PTR(value);
1174 lispobj first, *first_pointer;
1176 dprintf(weak_noise, ("Weak pointer at 0x%08x\n", (unsigned long) wp));
1177 dprintf(weak_noise, ("Value: 0x%08x\n", (unsigned long) value));
1179 if (Pointerp(value) && from_space_p(value)) {
1180 /* Now, we need to check if the object has been forwarded.
1181 * If it has been, the weak pointer is still good and needs
1182 * to be updated. Otherwise, the weak pointer needs to be nil'ed out.
1186 wp->value = FORWARDING_PTR(obj);
1187 else { /* break it */
1188 dprintf(weak_noise, ("Broken.\n"));
1197 scavenge_random_object(lispobj * addr)
1199 lispobj header = *addr;
1202 dprintf(noise > 1, ("soi: %x @ %x\n", header, addr));
1204 if (trapaddr == addr)
1207 gc_assert(ALIGNEDP(addr));
1209 switch (TypeOf(header)) {
1210 case type_SimpleVector:
1212 struct vector *v = (struct vector *) addr;
1213 int i, n = fixnum_value(v->length);
1215 if (HeaderValue(v->header) == subtype_VectorValidHashing)
1217 (subtype_VectorMustRehash << type_Bits) |
1219 /* Look at each of the vector elements which can be any lisp object. */
1220 for (i = 0; i < n; i++)
1221 scavenge_1word_obj(&v->data[i]);
1222 count = CEILING(n + 2, 2);
1225 case type_CodeHeader:
1226 count = scav_code_header(addr);
1228 /* We should never hit any of these, 'cause they occur buried in
1229 * the middle of code objects (and handled by the code just above).
1231 case type_ClosureFunctionHeader:
1232 case type_ReturnPcHeader:
1235 /* Except while looking at an fdefn and wanting to ensure
1236 * code object is looked at.
1238 case type_FunctionHeader:
1239 scavenge_fcn_header((struct function *) addr);
1242 case type_ClosureHeader:
1243 case type_FuncallableInstanceHeader:
1244 case type_ByteCodeFunction:
1245 case type_ByteCodeClosure:
1246 case type_DylanFunctionHeader:
1247 count = scav_closure_header((struct closure *) addr);
1250 case type_WeakPointer:
1251 count = scav_weak_pointer(addr);
1254 /* We have to handle fdefn objects specially, so we can fix
1255 * up the raw function address.
1257 count = scav_fdefn(addr);
1261 OSC_t class = sct[TypeOf(header)];
1263 switch (class.sc_kind) {
1269 int i, words = 1 + HeaderValue(header);
1271 for (i = 1; i < words; i++)
1272 scavenge_1word_obj(addr + i);
1273 count = CEILING(words, 2);
1278 case SC_VECTOR: /* simple vector handled above */
1279 count = sizeOfObject((obj_t) addr);
1290 logcopy(lispobj * addr, lispobj tagged, int hdr, lispobj to)
1293 int kind = TypeOf(hdr);
1294 int words = sizeOfObject((obj_t) PTR(tagged));
1296 fprintf(log, "(copy #x%x @ #x%x (#x%x %d) to #x%x)\n",
1297 tagged, addr, kind, words, to);
1301 maybe_transport(lispobj * addr, lispobj tagged, struct region *region)
1303 obj_t obj = (obj_t) PTR(tagged);
1305 gc_assert(ALIGNEDP(obj));
1306 gc_assert(Pointerp(tagged));
1307 gc_assert((void *) region != (void *) obj);
1309 if ((void *) obj == (void *) trapaddr)
1312 if (region->contains_small_objects) {
1313 lispobj new = copy(tagged);
1316 if (scav_ro > 1) /* debugging in RO space */
1319 #if defined GOOSE_CHASE
1320 if (TypeOf(obj->header) == type_Fdefn) {
1321 struct fdefn *fdefn = (struct fdefn *) PTR(new);
1323 if (fdefn->function < STATIC_SPACE_START)
1327 dprintf(0, ("copy %x @ %x (%x) to %x\n",
1328 tagged, addr, TypeOf(obj->header), new));
1329 logcopy(addr, tagged, obj->header, new);
1330 DEPOSIT_FORWARDING_PTR(obj, new);
1333 move_to_newspace(region);
1334 dprintf(0, ("move %x\n", region));
1339 scavenge_pointer(lispobj * addr)
1341 lispobj taggedobj = *addr; /* descriptor */
1342 obj_t obj = (obj_t) PTR(taggedobj); /* pointer to object */
1344 gc_assert(Pointerp(taggedobj));
1346 if (addr == trapaddr)
1348 if (obj == trapaddr)
1351 /* optimize out common static pointers */
1352 if (taggedobj != NIL && taggedobj != T) {
1353 struct region *region = find_region(obj);
1355 /* Only interested in pointers into oldspace */
1356 if (region && region->space == oldspace) {
1358 *addr = FORWARDING_PTR(obj);
1360 switch (LowtagOf(taggedobj)) {
1361 case type_ListPointer:
1362 dprintf(noise > 1, ("ListPointer @ %x...\n", addr));
1363 *addr = trans_list(taggedobj);
1364 dprintf(noise > 1, ("... -> %x\n", addr));
1366 case type_FunctionPointer:
1367 switch (TypeOf(obj->header)) {
1368 case type_ClosureHeader:
1369 case type_FuncallableInstanceHeader:
1370 case type_ByteCodeFunction:
1371 case type_ByteCodeClosure:
1372 case type_DylanFunctionHeader:
1373 maybe_transport(addr, taggedobj, region);
1379 case type_InstancePointer:
1380 case type_OtherPointer:
1381 maybe_transport(addr, taggedobj, region);
1384 /* It was a pointer, but not one of them? */
1393 scavenge(lispobj * addr, int ptrs)
1395 /* addr points to an aligned 32-bit word in some space. */
1396 struct region *region;
1397 lispobj *end = addr + ptrs;
1400 while (addr < end) {
1403 obj = *addr; /* the lisp object */
1405 if (trapaddr == addr)
1406 check_trap(addr); /* gdb breakpoint */
1408 if (Pointerp(obj)) /* lowtag odd */
1409 scavenge_pointer(addr);
1411 /* some other immediate */
1413 * Some random header. Process some type dependent number
1414 * of words. May still be inside object after call and the
1415 * next cell can be any lisp object. We can either recurse
1416 * by calling scavenge here or let the caller do it.
1418 count = scavenge_random_object(addr);
1428 scavenge_cons(lispobj * where)
1430 /* Scavenge a two-word space */
1431 scavenge_1word_obj(where + 0); /* car */
1432 scavenge_1word_obj(where + 1); /* cdr */
1435 scavenge_object(lispobj * start)
1437 int length = sizeOfObject((obj_t) start);
1438 int words = scavenge_random_object(start);
1440 gc_assert(length == words);
1441 return start + length;
1444 scavengex(lispobj * obj)
1446 /* Thing at this location is one of:
1447 * a - basic object with header.
1448 * b - cons object (no header).
1449 * so that the starting and ending addresses are aligned.
1451 gc_assert(ALIGNEDP(obj));
1453 lispobj first_word = *obj;
1454 OSC_t sc = sct[TypeOf(first_word)];
1456 if (Pointerp(first_word) || sc.sc_kind == SC_IMMED) { /* Must be a cons object or unused space */
1457 scavenge_cons((lispobj *) obj);
1459 } else { /* Must be a complex object with header */
1460 lispobj *next = scavenge_object(obj);
1468 scavenge_space(lispobj * where, int words, char *name)
1470 int allocated = bytes_allocated;
1471 lispobj *end = where + words;
1476 dprintf(noise, (" %s", name));
1477 while (where < end) {
1479 where = scavengex(last);
1481 gc_assert(where == end);
1483 dprintf(noise, (" %ld bytes moved, %ld bytes allocated.\n",
1484 bytes_copied, bytes_allocated - allocated));
1487 static int boxed_registers[] = BOXED_REGISTERS;
1489 preserve_interrupt_context(os_context_t * context)
1493 /* Check each boxed register for a valid pointer and promote
1494 * its region when found.
1496 for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {
1497 int index = boxed_registers[i];
1498 lispobj foo = SC_REG(context, index);
1499 struct region *region = find_region((void *) foo);
1501 if (region && region->space == oldspace)
1502 move_to_newspace(region);
1506 preserve_interrupt_contexts(void)
1509 os_context_t *context;
1511 index = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX));
1512 dprintf(noise, ("Number of active contexts: %d\n", index));
1514 for (i = 0; i < index; i++) {
1515 context = lisp_interrupt_contexts[i];
1516 preserve_interrupt_context(context);
1524 struct space *temp = oldspace;
1526 oldspace = newspace;
1530 /* There should be no lisp objects on the C stack so will limit search
1531 * to just the assigned lisp stack area.
1534 #define BOS (CONTROL_STACK_START+control_stack_size) /* x86-validate.h */
1535 /* Traverse stack in same direction as it was loaded to try and
1536 * preserve original ordering of pages. Good for the VM system I hope.
1538 #define ACROSS_STACK(var) var=(void**)BOS-1; var > (void**)&var; var--
1542 preserve_pointer(void *ptr)
1544 if (ptr > heap_base && ptr < heap_end) {
1545 struct region *region = find_region(ptr);
1547 if (region != NULL && region->space == oldspace) {
1548 dprintf(0, ("move %x\n", ptr));
1549 move_to_newspace(region);
1555 preserve_stack(void)
1557 void **addr; /* auto var is current TOS */
1559 for (ACROSS_STACK(addr))
1560 preserve_pointer(*addr);
1563 #ifdef CONTROL_STACKS
1564 /* Scavenge the thread stack conservative roots. */
1566 scavenge_thread_stacks(void)
1568 lispobj thread_stacks = SymbolValue(CONTROL_STACKS);
1569 int type = TypeOf(thread_stacks);
1571 if (LowtagOf(thread_stacks) == type_OtherPointer) {
1572 struct vector *vector = (struct vector *) PTR(thread_stacks);
1575 if (TypeOf(vector->header) != type_SimpleVector)
1577 length = fixnum_value(vector->length);
1578 for (i = 0; i < length; i++) {
1579 lispobj stack_obj = vector->data[i];
1581 if (LowtagOf(stack_obj) == type_OtherPointer) {
1582 struct vector *stack = (struct vector *) PTR(stack_obj);
1585 if (TypeOf(stack->header) != type_SimpleArrayUnsignedByte32)
1587 length = fixnum_value(stack->length);
1588 /* fprintf(stderr,"Scavenging control stack %d of length %d words\n",
1590 for (j = 0; j < length; j++)
1591 preserve_pointer((void *) stack->data[j]);
1601 /* This is a bit tricky because we don't want to zap any
1602 * stack frames between here and the call to mmap. For now,
1603 * lets just be slow and careful.
1606 os_vm_address_t base = (os_vm_address_t) CONTROL_STACK_START;
1607 os_vm_size_t size = (char *) &base - (char *) base;
1610 cgc_zero(base, size);
1620 #if defined STATIC_BLUE_BAG
1621 static int fast_static = 1;
1623 scavenge_static(void)
1625 /* Static space consists of alternating layers of
1626 * code objects that refer to read-only space (from purify),
1627 * static non-code objects that need looking at, and
1628 * newly loaded code objects that refer to dynamic space.
1629 * The number of these areas depends on how many times purify
1630 * ran while loading the system image. I will extend purify
1631 * to maintain a list of collectable areas and use that list
1632 * here to avoid scanning read-only code sections.
1634 lispobj *ss0 = (lispobj *) PTR(NIL);
1635 lispobj *ssa = (lispobj *) (PTR(STATIC_BLUE_BAG));
1636 lispobj *ssz = (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER);
1637 lispobj bag = SymbolValue(STATIC_BLUE_BAG);
1638 lispobj *end = NULL;
1640 ssa += sizeOfObject(OBJECT_AT(ssa)); /* Genesis modifies plist entry */
1642 scavenge_space(ss0, ssa - ss0, "Static0");
1643 if (bag != NIL && LowtagOf(bag) == type_ListPointer) {
1645 struct cons *cons = (struct cons *) PTR(bag);
1647 while (LowtagOf(cons->car) == type_ListPointer) {
1648 struct cons *pair = (struct cons *) PTR(cons->car);
1649 lispobj *ss1 = (lispobj *) pair->car;
1650 lispobj *ss2 = (lispobj *) pair->cdr;
1654 sprintf(sbuf, "Static %x %d", ss1, ss2 - ss1);
1655 scavenge_space(ss1, ss2 - ss1, sbuf);
1656 if (cons->cdr != NIL && LowtagOf(cons->cdr) == type_ListPointer)
1657 cons = (struct cons *) PTR(cons->cdr);
1663 scavenge_space(end, ssz - end, "Static");
1665 (scavenge_space(ss0, ssz - ss0, "Static-All"));
1670 scavenge_roots(void)
1672 /* So what should go here?
1673 * When cgc starts up after purify/save all live objects
1674 * are in read-only or static space, and anything in RO
1675 * can point only to RO or STATIC and can't be changed.
1676 * Anything in STATIC is subject to change (but not move).
1677 * . not read-only-space (probably most of the roots here)
1678 * . static-space (all compiled code at least)
1681 ? do I allow GC from interrupt?)
1682 * . interrupt-context (regs same as stack)
1684 * Well, it turns out that RO space ain't exactly that as
1685 * somehow apparently cached 'compact-info-environment' stuff
1686 * modifies at least 2 locations in RO space. There is a note
1687 * in globaldb.lisp that alludes to this and provides a post GC
1688 * hook to blow the cache. Not a problem if gc is called from
1689 * the lisp wrapper. UPDATE: Found purify bug which forced
1690 * boxed vectors into RO. This may be what led to above.
1693 lispobj *rs0 = (lispobj *) READ_ONLY_SPACE_START;
1694 lispobj *rsz = (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER);
1695 lispobj *ss0 = (lispobj *) STATIC_SPACE_START;
1696 lispobj *ssz = (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER);
1697 lispobj *bs0 = (lispobj *) BINDING_STACK_START;
1698 lispobj *bsz = (lispobj *) SymbolValue(BINDING_STACK_POINTER);
1702 scavenge_space(rs0, rsz - rs0, "RO");
1706 scavenge_space(bs0, bsz - bs0, "Binding Stack");
1708 dprintf(noise, ("Interrupt handlers (%u bytes) ...\n",
1709 sizeof(interrupt_handlers)));
1711 scavenge((lispobj *) interrupt_handlers,
1712 sizeof(interrupt_handlers) / sizeof(lispobj));
1717 scavenge_newspace(void)
1719 /* Scavenge is going to start at the beginning of newspace which
1720 * is presumed to have some "root" object pointers lying about due
1721 * to promoting regions that may be aimed at by stack resident pointers,
1722 * copied small objects from scavenge_roots(), or promoted large_object
1723 * regions. Scavenge() will flush out more copied objects/promoted
1724 * regions that will get added to the end of newspace and eventually
1725 * scanned by this code -- until all referenced things (and maybe some
1726 * extra dead stuff) have been examined. At the end of this loop anything
1727 * in oldspace is trash.
1729 struct region *current;
1731 current = newspace->regions;
1733 while (current != NULL) {
1734 if (current->contains_small_objects) {
1735 void *obj = (char *) current + REGION_OVERHEAD;
1736 void *end = (char *) current + current->num_chunks * CHUNK_BYTES;
1739 obj = SCAVENGE_OBJECT(OBJECT_AT(obj));
1740 gc_assert(obj == end);
1742 SCAVENGE_OBJECT(OBJECT_AT(((char *) current + REGION_OVERHEAD)));
1743 current = current->next;
1750 struct region *region, *next;
1753 for (region = oldspace->regions; region != NULL; region = next) {
1754 gc_assert(region->space != newspace);
1755 next = region->next;
1756 free_region(region);
1758 oldspace->alloc_ptr = NULL;
1759 oldspace->alloc_end = NULL;
1760 oldspace->regions = NULL;
1761 oldspace->regions_tail = &oldspace->regions;
1765 verify_space(lispobj * start, size_t words)
1769 lispobj thing = *(lispobj *) start;
1771 if (Pointerp(thing)) {
1772 struct region *region = find_region((void *) thing);
1774 if (region && region->space == NULL)
1775 fprintf(stderr, "Ptr %x @ %x sees Junk\n", thing, start);
1776 } else if (thing & 0x3) {
1777 obj_t obj = (obj_t) start;
1779 switch (TypeOf(obj->header)) {
1780 case type_CodeHeader:
1782 lispobj object = *start;
1784 int nheader_words, ncode_words, nwords;
1786 struct function *fheaderp;
1788 code = (struct code *) start;
1789 ncode_words = fixnum_value(code->code_size);
1790 nheader_words = HeaderValue(object);
1791 nwords = ncode_words + nheader_words;
1792 nwords = CEILING(nwords, 2);
1793 /* Scavenge the boxed section of the code data block */
1794 verify_space(start + 1, nheader_words - 1);
1796 /* Scavenge the boxed section of each function object in the
1799 fheaderl = code->entry_points;
1800 while (fheaderl != NIL) {
1801 fheaderp = (struct function *) PTR(fheaderl);
1802 gc_assert(TypeOf(fheaderp->header) ==
1803 type_FunctionHeader);
1804 verify_space(&fheaderp->name, 1);
1805 verify_space(&fheaderp->arglist, 1);
1806 verify_space(&fheaderp->type, 1);
1807 fheaderl = fheaderp->next;
1814 OSC_t class = sct[TypeOf(obj->header)];
1816 switch (class.sc_kind) {
1824 count = sizeOfObject((obj_t) start);
1838 /* For debug/test only. */
1842 lispobj *rs0 = (lispobj *) READ_ONLY_SPACE_START;
1843 lispobj *rsz = (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER);
1844 lispobj *ss0 = (lispobj *) STATIC_SPACE_START;
1845 lispobj *ssz = (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER);
1846 lispobj *bs0 = (lispobj *) BINDING_STACK_START;
1847 lispobj *bsz = (lispobj *) SymbolValue(BINDING_STACK_POINTER);
1848 lispobj *cs0 = (lispobj *) & rs0;
1849 lispobj *csz = (lispobj *) BOS;
1851 /* can't check stack easily because there may be non-valid
1852 * objects there (thats why we're doing this cgc stuff). In
1853 * particular there are raw return addresses which can be very
1854 * descriptorish looking!!!
1856 verify_space(cs0, csz-cs0);
1858 verify_space(rs0, rsz - rs0);
1859 verify_space(ss0, ssz - ss0);
1860 verify_space(bs0, bsz - bs0);
1863 fixup_regions(struct region *region)
1866 lispobj header = (lispobj) OBJECT_AT(region)->header;
1868 if (static_space_p(header)) {
1869 /* Purify thought this header was a cons? Why? */
1870 struct cons *wrong = (struct cons *) PTR(header);
1871 struct cons *fixme = (struct cons *) region;
1873 dprintf(1, ("\n--Fixing region header @ %x.", region));
1874 fixme->car = wrong->car; /* restore region header */
1875 fixme->cdr = wrong->cdr; /* restore prev pointer */
1876 wrong->car = wrong->cdr = 0;
1878 region = region->next;
1880 while (region != NULL);
1884 post_purify_fixup(struct space *space)
1886 /* Purify may have messed up the region headers. This can happen
1887 * if there is a dead list pointer on the stack that now aims
1888 * at a region header (previously was valid memory). Purify attempts
1889 * to at least check for a valid object header but loses with lists.
1890 * This hack recovers the correct values and keeps us going. Can
1891 * this occur with other dead objects?
1893 if (large_region_free_list)
1894 fixup_regions(large_region_free_list);
1895 if (small_region_free_list)
1896 fixup_regions(small_region_free_list);
1897 fixup_regions(space->regions);
1901 static int dolog = 0; /* log copy ops to file */
1902 static int dover = 0; /* hunt pointers to oldspace */
1904 cgc_collect_garbage(void)
1906 unsigned long allocated = bytes_allocated;
1908 dprintf(noise, ("GC\n"));
1910 log = fopen("LOG.tmp", "w");
1912 /* Initialize the weak pointer list. */
1913 weak_pointers = NULL;
1915 dprintf(noise, ("[Flip Spaces]\n"));
1917 preserve_interrupt_contexts();
1918 dprintf(noise, ("[Preserve Stack]\n"));
1920 scavenge_thread_stacks();
1921 dprintf(noise, ("[Scavenge Roots]\n"));
1923 dprintf(noise, ("[Scavenge New]\n"));
1924 scavenge_newspace();
1925 scan_weak_pointers();
1926 dprintf(noise, ("[Free Oldspace]\n"));
1929 dprintf(noise, ("[Checking]\n"));
1932 dprintf(noise, ("[Compacting]\n"));
1933 compact_free_regions();
1934 /* The stack will be zeroed by scrub-control-stack in sub-gc which
1935 is more effecient. */
1940 dprintf(noise, (" %ld bytes copied.\n", (bytes_allocated - allocated)));
1941 dprintf(noise, (" %ld bytes (%ld pages) reclaimed.\n",
1942 chunks_freed * CHUNK_BYTES, chunks_freed));
1943 bytes_allocated -= chunks_freed * CHUNK_BYTES;
1944 maybe_gc_called = 0;
1950 /* Like above but just zap everything 'cause purify has
1953 unsigned long allocated = bytes_allocated;
1956 post_purify_fixup(oldspace);
1958 compact_free_regions();
1959 #if 0 /* purify is currently running on the C stack so don't do this */
1962 bytes_allocated -= chunks_freed * CHUNK_BYTES;
1967 cgc_init_collector(void)
1971 heap_base = (void *) DYNAMIC_0_SPACE_START;
1973 /* I could actually use both spaces here but just 1 for now */
1974 heap_end = (char *) heap_base + dynamic_space_size;
1976 max_blocks = BLOCK_NUMBER(heap_end) - BLOCK_NUMBER(heap_base);
1977 if ((block_table_base = malloc(sizeof(struct cluster *) * max_blocks))
1979 memset(block_table_base, 0, sizeof(struct cluster *) * max_blocks);
1981 block_table = (block_table_base - BLOCK_NUMBER(heap_base));
1983 space_0.regions_tail = &space_0.regions;
1984 space_1.regions_tail = &space_1.regions;
1986 newspace = &space_0;
1987 oldspace = &space_1;
1989 perror("malloc cgc block table");
1990 init_osc(); /* Object Storage Class table */
1994 void do_pending_interrupt(void);
2000 /* Alloc is only called from lisp code to allocate a number of
2001 words, the cgc GC uses cgc_alloc directly as the checks of the
2002 heap size and is not needed and interrupts are allways disabled
2005 /* Assumes nbytes includes alignment. Python arranges for that
2006 * but the C startup code needed some help.
2009 int bytes = (nbytes + (ALIGN_BYTES - 1)) & ~(ALIGN_BYTES - 1);
2011 if (bytes != nbytes)
2012 fprintf(stderr, "Fixing unaligned allocation length %d.\n", nbytes);
2016 char *current = (char *) SymbolValue(ALLOCATION_POINTER);
2017 char *nxtfree = current + nbytes;
2019 SetSymbolValue(ALLOCATION_POINTER, (lispobj) nxtfree);
2022 /* Lacking an interrupt driven scheme to notice when a GC might
2023 * be wise, we add some more overhead to the allocator here
2024 * before any needed state is acquired. Only need to do it once
2025 * though because lisp will remember *need to collect garbage*
2026 * and get to it when it can. */
2027 if (auto_gc_trigger /* Only when enabled */
2028 && bytes_allocated > auto_gc_trigger && !maybe_gc_called++) /* Only once */
2029 funcall0(SymbolFunction(MAYBE_GC));
2031 if (SymbolValue(INTERRUPTS_ENABLED) == NIL)
2032 /* Interrupts are disable so no special care is needed */
2033 return cgc_alloc(nbytes);
2037 /* Interrupts are enabled so set *interrupt-enabled* to nil
2038 before calling cgc_alloc to prevent cgc_alloc from being
2040 SetSymbolValue(INTERRUPTS_ENABLED, NIL);
2042 result = cgc_alloc(nbytes);
2044 /* Restore *interrupts-enabled* */
2045 SetSymbolValue(INTERRUPTS_ENABLED, T);
2047 /* Check if an interrupt occured */
2048 if (SymbolValue(INTERRUPT_PENDING) == T)
2049 /* Handle any interrupts that occured during cgc_alloc */
2050 do_pending_interrupt();
2057 /* Interface to history. */
2059 set_auto_gc_trigger(unsigned long dynamic_usage)
2061 auto_gc_trigger += dynamic_usage;
2065 clear_auto_gc_trigger(void)
2067 auto_gc_trigger = 0;
2073 cgc_init_collector();
2077 collect_garbage(void)
2079 /* SUB-GC wraps without-interrupt around call, but this
2080 * is going to absolutely block SIGINT.
2082 /* #define REALLY_SAFE */
2083 #if defined REALLY_SAFE
2084 sigset_t newmask, oldmask;
2086 sigemptyset(&newmask);
2087 sigaddset(&newmask, SIGINT);
2088 sigprocmask(SIG_BLOCK, &newmask, &oldmask);
2090 cgc_collect_garbage();
2091 #if defined REALLY_SAFE
2092 sigprocmask(SIG_SETMASK, &oldmask, NULL);
2097 /* Some helpers for the debugger. */
2099 /* Scan an area looking for an object which encloses the given
2100 pointer. Returns the object start on success or NULL on failure. */
2102 search_space(lispobj * start, size_t words, lispobj * pointer)
2106 lispobj thing = *start;
2108 /* If thing is an immediate then this is a cons */
2110 || ((thing & 3) == 0) /* fixnum */
2111 ||(TypeOf(thing) == type_BaseChar)
2112 || (TypeOf(thing) == type_UnboundMarker))
2115 count = sizeOfObject((obj_t) start);
2117 /* Check if the pointer is within this object? */
2118 if ((pointer >= start) && (pointer < (start + count))) {
2120 /* fprintf(stderr,"* Found %x in %x %x\n",pointer, start, thing); */
2124 /* Round up the count */
2125 count = CEILING(count, 2);
2134 search_read_only_space(lispobj * pointer)
2136 lispobj *start = (lispobj *) READ_ONLY_SPACE_START;
2137 lispobj *end = (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER);
2139 if ((pointer < start) || (pointer >= end))
2141 return (search_space(start, (pointer + 2) - start, pointer));
2145 search_static_space(lispobj * pointer)
2147 lispobj *start = (lispobj *) STATIC_SPACE_START;
2148 lispobj *end = (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER);
2150 if ((pointer < start) || (pointer >= end))
2152 return (search_space(start, (pointer + 2) - start, pointer));
2155 /* Find the code object for the given pc. Return NULL on failure */
2157 component_ptr_from_pc(lispobj * pc)
2159 lispobj *object = NULL;
2161 if (object = search_read_only_space(pc));
2163 object = search_static_space(pc);
2165 /* Found anything? */
2167 /* Check if it is a code object. */
2168 if (TypeOf(*object) == type_CodeHeader)