3 This code is based on public domain codes from CMUCL. It is placed
4 in the public domain and is provided as-is.
6 Stack direction changes, the x86/CGC stack scavenging, and static
7 blue bag feature, by Paul Werkowski, 1995, 1996.
9 Bug fixes, x86 code movement support, the scavenger hook support,
10 and x86/GENCGC stack scavenging, by Douglas Crosher, 1996, 1997,
15 #include <sys/types.h>
22 #include "internals.h"
25 #include "interrupt.h"
34 #if (defined(i386) || defined(__x86_64))
35 static lispobj *current_dynamic_space_free_pointer;
38 #define gc_abort() lose("GC invariant lost! File \"%s\", line %d\n", \
42 #define gc_assert(ex) do { \
43 if (!(ex)) gc_abort(); \
50 #define assert_static_space_bounds(ptr) do { \
51 if (!((lispobj*)STATIC_SPACE_START <= ptr && ptr < (lispobj*)(STATIC_SPACE_START + static_space_size))) \
52 lose ("static-space overflow! File \"%s\", line %d\n", \
53 __FILE__, __LINE__); \
56 #define assert_readonly_space_bounds(ptr) do { \
57 if (!((lispobj*)READ_ONLY_SPACE_START <= ptr && ptr < (lispobj*)(READ_ONLY_SPACE_START + read_only_space_size))) \
58 lose ("readonly-space overflow! File \"%s\", line %d\n", \
59 __FILE__, __LINE__); \
64 /* These hold the original end of the read_only and static spaces so we can */
65 /* tell what are forwarding pointers. */
67 static lispobj *read_only_end, *static_end;
69 static lispobj *read_only_free, *static_free;
70 static lispobj *pscav(lispobj * addr, int nwords, boolean constant);
72 #define LATERBLOCKSIZE 1020
73 #define LATERMAXCOUNT 10
81 } *later_blocks = NULL;
82 static int later_count = 0;
84 #define CEILING(x,y) (((x) + ((y) - 1)) & (~((y) - 1)))
85 #define NWORDS(x,y) (CEILING((x),(y)) / (y))
87 #if defined(sparc) || (defined(DARWIN) && defined(__ppc__))
88 #define RAW_ADDR_OFFSET 0
90 #define RAW_ADDR_OFFSET (6*sizeof(lispobj) - type_FunctionPointer)
94 forwarding_pointer_p(lispobj obj)
98 ptr = (lispobj *) obj;
100 return ((static_end <= ptr && ptr <= static_free) ||
101 (read_only_end <= ptr && ptr <= read_only_free));
105 dynamic_pointer_p(lispobj ptr)
107 #if !(defined(i386) || defined(__x86_64))
108 return (ptr >= (lispobj) dynamic_0_space);
110 /* Be more conservative, and remember, this is a maybe */
111 return (ptr >= (lispobj) current_dynamic_space
112 && ptr < (lispobj) current_dynamic_space_free_pointer);
117 #if (defined(i386) || defined(__x86_64))
120 /* Original x86/CGC stack scavenging code by Paul Werkowski */
123 maybe_can_move_p(lispobj thing)
125 lispobj *thingp, header;
127 if (dynamic_pointer_p(thing)) { /* in dynamic space */
128 thingp = (lispobj *) PTR(thing);
130 if (Pointerp(header) && forwarding_pointer_p(header))
131 return -1; /* must change it */
132 if (LowtagOf(thing) == type_ListPointer)
133 return type_ListPointer; /* can we check this somehow */
134 else if (thing & 3) { /* not fixnum */
135 int kind = TypeOf(header);
137 /* printf(" %x %x",header,kind); */
138 switch (kind) { /* something with a header */
140 case type_SingleFloat:
141 case type_DoubleFloat:
142 #ifdef type_LongFloat
145 #ifdef type_DoubleDoubleFloat
146 case type_DoubleDoubleFloat:
149 case type_SimpleVector:
150 case type_SimpleString:
151 case type_SimpleBitVector:
152 case type_SimpleArrayUnsignedByte2:
153 case type_SimpleArrayUnsignedByte4:
154 case type_SimpleArrayUnsignedByte8:
155 case type_SimpleArrayUnsignedByte16:
156 case type_SimpleArrayUnsignedByte32:
157 #ifdef type_SimpleArraySignedByte8
158 case type_SimpleArraySignedByte8:
160 #ifdef type_SimpleArraySignedByte16
161 case type_SimpleArraySignedByte16:
163 #ifdef type_SimpleArraySignedByte30
164 case type_SimpleArraySignedByte30:
166 #ifdef type_SimpleArraySignedByte32
167 case type_SimpleArraySignedByte32:
169 case type_SimpleArraySingleFloat:
170 case type_SimpleArrayDoubleFloat:
171 #ifdef type_SimpleArrayLongFloat
172 case type_SimpleArrayLongFloat:
174 #ifdef type_SimpleArrayDoubleDoubleFloat
175 case type_SimpleArrayDoubleDoubleFloat:
177 #ifdef type_SimpleArrayComplexSingleFloat
178 case type_SimpleArrayComplexSingleFloat:
180 #ifdef type_SimpleArrayComplexDoubleFloat
181 case type_SimpleArrayComplexDoubleFloat:
183 #ifdef type_SimpleArrayComplexLongFloat
184 case type_SimpleArrayComplexLongFloat:
186 #ifdef type_SimpleArrayComplexDoubleDoubleFloat
187 case type_SimpleArrayComplexDoubleDoubleFloat:
189 case type_CodeHeader:
190 case type_FunctionHeader:
191 case type_ClosureFunctionHeader:
192 case type_ReturnPcHeader:
193 case type_ClosureHeader:
194 case type_FuncallableInstanceHeader:
195 case type_InstanceHeader:
196 case type_ValueCellHeader:
197 case type_ByteCodeFunction:
198 case type_ByteCodeClosure:
199 #ifdef type_DylanFunctionHeader
200 case type_DylanFunctionHeader:
202 case type_WeakPointer:
204 #ifdef type_ScavengerHook
205 case type_ScavengerHook:
217 static int pverbose = 0;
219 #define PVERBOSE pverbose
221 carefully_pscav_stack(lispobj * lowaddr, lispobj * base)
223 lispobj *sp = lowaddr;
229 if ((unsigned) thing & 0x3) { /* may be pointer */
230 /* need to check for valid float/double? */
231 k = maybe_can_move_p(thing);
233 printf("%8x %8x %d\n", sp, thing, k);
242 #if defined(GENCGC) && (defined(i386) || defined(__x86_64))
244 * Enhanced x86/GENCGC stack scavenging by Douglas Crosher.
246 * Scavenging the stack on the i386 is problematic due to conservative
247 * roots and raw return addresses. Here it is handled in two passes:
248 * the first pass runs before any objects are moved and tries to
249 * identify valid pointers and return address on the stack, the second
250 * pass scavenges these.
253 static unsigned pointer_filter_verbose = 0;
256 valid_dynamic_space_pointer(lispobj * pointer, lispobj * start_addr)
258 /* If it's not a return address then it needs to be a valid lisp
260 if (!Pointerp((lispobj) pointer))
263 /* Check that the object pointed to is consistent with the pointer
265 switch (LowtagOf((lispobj) pointer)) {
266 case type_FunctionPointer:
267 /* Start_addr should be the enclosing code object, or a closure
269 switch (TypeOf(*start_addr)) {
270 case type_CodeHeader:
271 /* This case is probably caught above. */
273 case type_ClosureHeader:
274 case type_FuncallableInstanceHeader:
275 case type_ByteCodeFunction:
276 case type_ByteCodeClosure:
277 #ifdef type_DylanFunctionHeader
278 case type_DylanFunctionHeader:
280 if ((int) pointer != ((int) start_addr + type_FunctionPointer)) {
281 if (pointer_filter_verbose)
282 fprintf(stderr, "*Wf2: %p %p %lx\n", pointer,
283 start_addr, *start_addr);
288 if (pointer_filter_verbose)
289 fprintf(stderr, "*Wf3: %p %p %lx\n", pointer, start_addr,
294 case type_ListPointer:
295 if ((int) pointer != ((int) start_addr + type_ListPointer)) {
296 if (pointer_filter_verbose)
297 fprintf(stderr, "*Wl1: %p %p %lx\n", pointer, start_addr,
301 /* Is it plausible cons? */
302 if ((Pointerp(start_addr[0])
303 || ((start_addr[0] & 3) == 0) /* fixnum */
304 ||(TypeOf(start_addr[0]) == type_BaseChar)
305 || (TypeOf(start_addr[0]) == type_UnboundMarker))
306 && (Pointerp(start_addr[1])
307 || ((start_addr[1] & 3) == 0) /* fixnum */
308 ||(TypeOf(start_addr[1]) == type_BaseChar)
309 || (TypeOf(start_addr[1]) == type_UnboundMarker)))
312 if (pointer_filter_verbose)
313 fprintf(stderr, "*Wl2: %p %p %lx\n", pointer, start_addr,
317 case type_InstancePointer:
318 if ((int) pointer != ((int) start_addr + type_InstancePointer)) {
319 if (pointer_filter_verbose)
320 fprintf(stderr, "*Wi1: %p %p %lx\n", pointer, start_addr,
324 if (TypeOf(start_addr[0]) != type_InstanceHeader) {
325 if (pointer_filter_verbose)
326 fprintf(stderr, "*Wi2: %p %p %lx\n", pointer, start_addr,
331 case type_OtherPointer:
332 if ((int) pointer != ((int) start_addr + type_OtherPointer)) {
333 if (pointer_filter_verbose)
334 fprintf(stderr, "*Wo1: %p %p %lx\n", pointer, start_addr,
338 /* Is it plausible? Not a cons. X should check the headers. */
339 if (Pointerp(start_addr[0]) || ((start_addr[0] & 3) == 0)) {
340 if (pointer_filter_verbose)
341 fprintf(stderr, "*Wo2: %p %p %lx\n", pointer, start_addr,
345 switch (TypeOf(start_addr[0])) {
346 case type_UnboundMarker:
348 if (pointer_filter_verbose)
349 fprintf(stderr, "*Wo3: %p %p %lx\n", pointer, start_addr,
353 /* Only pointed to by function pointers? */
354 case type_ClosureHeader:
355 case type_FuncallableInstanceHeader:
356 case type_ByteCodeFunction:
357 case type_ByteCodeClosure:
358 #ifdef type_DylanFunctionHeader
359 case type_DylanFunctionHeader:
361 if (pointer_filter_verbose)
362 fprintf(stderr, "*Wo4: %p %p %lx\n", pointer, start_addr,
366 case type_InstanceHeader:
367 if (pointer_filter_verbose)
368 fprintf(stderr, "*Wo5: %p %p %lx\n", pointer, start_addr,
372 /* The valid other immediate pointer objects */
373 case type_SimpleVector:
376 #ifdef type_ComplexSingleFloat
377 case type_ComplexSingleFloat:
379 #ifdef type_ComplexDoubleFloat
380 case type_ComplexDoubleFloat:
382 #ifdef type_ComplexLongFloat
383 case type_ComplexLongFloat:
385 #ifdef type_ComplexDoubleDoubleFloat
386 case type_ComplexDoubleDoubleFloat:
388 case type_SimpleArray:
389 case type_ComplexString:
390 case type_ComplexBitVector:
391 case type_ComplexVector:
392 case type_ComplexArray:
393 case type_ValueCellHeader:
394 case type_SymbolHeader:
396 case type_CodeHeader:
398 case type_SingleFloat:
399 case type_DoubleFloat:
400 #ifdef type_LongFloat
403 #ifdef type_DoubleDoubleFloat
404 case type_DoubleDoubleFloat:
406 case type_SimpleString:
407 case type_SimpleBitVector:
408 case type_SimpleArrayUnsignedByte2:
409 case type_SimpleArrayUnsignedByte4:
410 case type_SimpleArrayUnsignedByte8:
411 case type_SimpleArrayUnsignedByte16:
412 case type_SimpleArrayUnsignedByte32:
413 #ifdef type_SimpleArraySignedByte8
414 case type_SimpleArraySignedByte8:
416 #ifdef type_SimpleArraySignedByte16
417 case type_SimpleArraySignedByte16:
419 #ifdef type_SimpleArraySignedByte30
420 case type_SimpleArraySignedByte30:
422 #ifdef type_SimpleArraySignedByte32
423 case type_SimpleArraySignedByte32:
425 case type_SimpleArraySingleFloat:
426 case type_SimpleArrayDoubleFloat:
427 #ifdef type_SimpleArrayLongFloat
428 case type_SimpleArrayLongFloat:
430 #ifdef type_SimpleArrayDoubleDoubleFloat
431 case type_SimpleArrayDoubleDoubleFloat:
433 #ifdef type_SimpleArrayComplexSingleFloat
434 case type_SimpleArrayComplexSingleFloat:
436 #ifdef type_SimpleArrayComplexDoubleFloat
437 case type_SimpleArrayComplexDoubleFloat:
439 #ifdef type_SimpleArrayComplexLongFloat
440 case type_SimpleArrayComplexLongFloat:
442 #ifdef type_SimpleArrayComplexDoubleDoubleFloat
443 case type_SimpleArrayComplexDoubleDoubleFloat:
446 case type_WeakPointer:
447 case type_ScavengerHook:
451 if (pointer_filter_verbose)
452 fprintf(stderr, "*Wo6: %p %p %lx\n", pointer, start_addr,
458 if (pointer_filter_verbose)
459 fprintf(stderr, "*W?: %p %p %lx\n", pointer, start_addr,
468 #define MAX_STACK_POINTERS 1024
469 lispobj *valid_stack_locations[MAX_STACK_POINTERS];
470 unsigned int num_valid_stack_locations;
472 #define MAX_STACK_RETURN_ADDRESSES 128
473 lispobj *valid_stack_ra_locations[MAX_STACK_RETURN_ADDRESSES];
474 lispobj *valid_stack_ra_code_objects[MAX_STACK_RETURN_ADDRESSES];
475 unsigned int num_valid_stack_ra_locations;
478 * Identify valid stack slots.
482 setup_i386_stack_scav(lispobj * lowaddr, lispobj * base)
484 lispobj *sp = lowaddr;
486 num_valid_stack_locations = 0;
487 num_valid_stack_ra_locations = 0;
489 for (sp = lowaddr; sp < base; sp++) {
493 /* Find the object start address */
494 if ((start_addr = search_dynamic_space((void *) thing)) != NULL) {
496 * Need to allow raw pointers into Code objects for return
497 * addresses. This will also pickup pointers to functions in code
500 if (TypeOf(*start_addr) == type_CodeHeader) {
501 gc_assert(num_valid_stack_ra_locations <
502 MAX_STACK_RETURN_ADDRESSES);
503 valid_stack_ra_locations[num_valid_stack_ra_locations] = sp;
504 valid_stack_ra_code_objects[num_valid_stack_ra_locations++] =
505 (lispobj *) ((int) start_addr + type_OtherPointer);
507 if (valid_dynamic_space_pointer((void *) thing, start_addr)) {
508 gc_assert(num_valid_stack_locations < MAX_STACK_POINTERS);
509 valid_stack_locations[num_valid_stack_locations++] = sp;
514 if (pointer_filter_verbose) {
515 fprintf(stderr, "Number of valid stack pointers = %d\n",
516 num_valid_stack_locations);
517 fprintf(stderr, "Number of stack return addresses = %d\n",
518 num_valid_stack_ra_locations);
523 pscav_i386_stack(void)
527 for (i = 0; i < num_valid_stack_locations; i++)
528 pscav(valid_stack_locations[i], 1, FALSE);
530 for (i = 0; i < num_valid_stack_ra_locations; i++) {
531 lispobj code_obj = (lispobj) (valid_stack_ra_code_objects[i]);
533 pscav(&code_obj, 1, FALSE);
534 if (pointer_filter_verbose)
536 "*C moved RA %lx to %x; for code object %p to %lx\n",
537 *valid_stack_ra_locations[i],
538 (int) (*valid_stack_ra_locations[i])
539 - ((int) valid_stack_ra_code_objects[i] - (int) code_obj),
540 valid_stack_ra_code_objects[i], code_obj);
541 *valid_stack_ra_locations[i] =
542 (lispobj) ((int) (*valid_stack_ra_locations[i])
543 - ((int) valid_stack_ra_code_objects[i] -
552 pscav_later(lispobj * where, int count)
556 if (count > LATERMAXCOUNT) {
557 while (count > LATERMAXCOUNT) {
558 pscav_later(where, LATERMAXCOUNT);
559 count -= LATERMAXCOUNT;
560 where += LATERMAXCOUNT;
563 if (later_blocks == NULL || later_count == LATERBLOCKSIZE ||
564 (later_count == LATERBLOCKSIZE - 1 && count > 1)) {
565 new = (struct later *) malloc(sizeof(struct later));
567 new->next = later_blocks;
568 if (later_blocks && later_count < LATERBLOCKSIZE)
569 later_blocks->u[later_count].ptr = NULL;
575 later_blocks->u[later_count++].count = count;
576 later_blocks->u[later_count++].ptr = where;
581 ptrans_boxed(lispobj thing, lispobj header, boolean constant)
584 lispobj result, *new, *old;
586 nwords = 1 + HeaderValue(header);
589 old = (lispobj *) PTR(thing);
591 new = read_only_free;
592 read_only_free += CEILING(nwords, 2);
593 assert_readonly_space_bounds(read_only_free);
596 static_free += CEILING(nwords, 2);
597 assert_static_space_bounds(static_free);
601 memmove(new, old, nwords * sizeof(lispobj));
603 /* Deposit forwarding pointer. */
604 result = (lispobj) new | LowtagOf(thing);
608 pscav(new, nwords, constant);
613 /* need to look at the layout to see if it is a pure structure class, and
614 only then can we transport as constant. If it is pure, we can
615 ALWAYS transport as a constant */
618 ptrans_instance(lispobj thing, lispobj header, boolean constant)
620 lispobj layout = ((struct instance *) PTR(thing))->slots[0];
621 lispobj pure = ((struct instance *) PTR(layout))->slots[15];
625 return (ptrans_boxed(thing, header, 1));
627 return (ptrans_boxed(thing, header, 0));
629 /* Substructure: special case for the compact-info-envs, where
630 the instance may have a point to the dynamic space placed
631 into it (e.g. the cache-name slot), but the lists and arrays
632 at the time of a purify can be moved to the RO space. */
634 lispobj result, *new, *old;
636 nwords = 1 + HeaderValue(header);
639 old = (lispobj *) PTR(thing);
641 static_free += CEILING(nwords, 2);
642 assert_static_space_bounds(static_free);
645 memmove(new, old, nwords * sizeof(lispobj));
647 /* Deposit forwarding pointer. */
648 result = (lispobj) new | LowtagOf(thing);
652 pscav(new, nwords, 1);
658 return 0; /* squelch stupid warning */
663 ptrans_fdefn(lispobj thing, lispobj header)
666 lispobj result, *new, *old, oldfn;
669 nwords = 1 + HeaderValue(header);
672 old = (lispobj *) PTR(thing);
674 static_free += CEILING(nwords, 2);
675 assert_static_space_bounds(static_free);
678 memmove(new, old, nwords * sizeof(lispobj));
680 /* Deposit forwarding pointer. */
681 result = (lispobj) new | LowtagOf(thing);
684 /* Scavenge the function. */
685 fdefn = (struct fdefn *) new;
686 oldfn = fdefn->function;
687 pscav(&fdefn->function, 1, FALSE);
688 if ((char *) oldfn + RAW_ADDR_OFFSET == fdefn->raw_addr)
689 fdefn->raw_addr = (char *) fdefn->function + RAW_ADDR_OFFSET;
695 ptrans_unboxed(lispobj thing, lispobj header)
698 lispobj result, *new, *old;
700 nwords = 1 + HeaderValue(header);
703 old = (lispobj *) PTR(thing);
704 new = read_only_free;
705 read_only_free += CEILING(nwords, 2);
706 assert_readonly_space_bounds(read_only_free);
709 memmove(new, old, nwords * sizeof(lispobj));
711 /* Deposit forwarding pointer. */
712 result = (lispobj) new | LowtagOf(thing);
719 ptrans_vector(lispobj thing, int bits, int extra,
720 boolean boxed, boolean constant)
722 struct vector *vector;
724 lispobj result, *new;
726 vector = (struct vector *) PTR(thing);
729 2 + (CEILING((fixnum_value(vector->length) + extra) * bits, 64) >> 6);
732 2 + (CEILING((fixnum_value(vector->length) + extra) * bits, 32) >> 5);
735 if (boxed && !constant) {
737 static_free += CEILING(nwords, 2);
738 assert_static_space_bounds(static_free);
740 new = read_only_free;
741 read_only_free += CEILING(nwords, 2);
742 assert_readonly_space_bounds(read_only_free);
745 memmove(new, vector, nwords * sizeof(lispobj));
747 result = (lispobj) new | LowtagOf(thing);
748 vector->header = result;
751 pscav(new, nwords, constant);
756 #if (defined(i386) || defined(__x86_64))
758 apply_code_fixups_during_purify(struct code *old_code, struct code *new_code)
760 int nheader_words, ncode_words, nwords;
761 void *code_start_addr;
762 lispobj fixups = NIL;
763 unsigned displacement = (unsigned) new_code - (unsigned) old_code;
764 struct vector *fixups_vector;
766 /* Byte compiled code has no fixups. The trace table offset will be
767 a fixnum if it's x86 compiled code - check. */
768 if (new_code->trace_table_offset & 0x3)
771 /* Else it's x86 machine code. */
772 ncode_words = fixnum_value(new_code->code_size);
773 nheader_words = HeaderValue(*(lispobj *) new_code);
774 nwords = ncode_words + nheader_words;
776 code_start_addr = (void *) new_code + nheader_words * sizeof(lispobj);
778 /* The first constant should be a pointer to the fixups for this
779 code objects. Check. */
780 fixups = new_code->constants[0];
782 /* It will be 0 or the unbound-marker if there are no fixups, and
783 will be an other-pointer to a vector if it is valid. */
784 if ((fixups == 0) || (fixups == type_UnboundMarker) || !Pointerp(fixups)) {
785 #if defined(GENCGC) && (defined(i386) || defined(__x86_64))
786 /* Check for a possible errors. */
787 sniff_code_object(new_code, displacement);
792 fixups_vector = (struct vector *) PTR(fixups);
794 /* Could be pointing to a forwarding pointer. */
795 if (Pointerp(fixups) && (dynamic_pointer_p(fixups))
796 && forwarding_pointer_p(*(lispobj *) fixups_vector)) {
797 /* If so then follow it. */
798 fixups_vector = (struct vector *) PTR(*(lispobj *) fixups_vector);
801 if (TypeOf(fixups_vector->header) == type_SimpleArrayUnsignedByte32) {
802 /* Got the fixups for the code block. Now work through the vector,
803 and apply a fixup at each address. */
804 int length = fixnum_value(fixups_vector->length);
806 /* offset_vector still has 32-bit elements on amd64.
807 Eventually we will make this consistent with internals.h */
808 unsigned int *offset_vector = (unsigned int *) fixups_vector->data;
811 for (i = 0; i < length; i++) {
812 unsigned offset = offset_vector[i];
814 /* Now check the current value of offset. */
817 *(unsigned *) ((unsigned) code_start_addr + offset);
819 /* If it's within the old_code object then it must be an
820 absolute fixup (relative ones are not saved) */
821 if ((old_value >= (unsigned) old_code)
823 ((unsigned) old_code + nwords * sizeof(lispobj))))
824 /* So add the dispacement. */
825 *(unsigned *) ((unsigned) code_start_addr + offset) = old_value
828 /* It is outside the old code object so it must be a relative
829 fixup (absolute fixups are not saved). So subtract the
831 *(unsigned *) ((unsigned) code_start_addr + offset) = old_value
836 /* No longer need the fixups. */
837 new_code->constants[0] = 0;
839 #if defined(GENCGC) && (defined(i386) || defined(__x86_64))
840 /* Check for possible errors. */
841 sniff_code_object(new_code, displacement);
847 ptrans_code(lispobj thing)
849 struct code *code, *new;
851 lispobj func, result;
853 code = (struct code *) PTR(thing);
854 nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
856 new = (struct code *) read_only_free;
857 read_only_free += CEILING(nwords, 2);
858 assert_readonly_space_bounds(read_only_free);
860 memmove(new, code, nwords * sizeof(lispobj));
862 #if (defined(i386) || defined(__x86_64))
863 apply_code_fixups_during_purify(code, new);
866 result = (lispobj) new | type_OtherPointer;
868 /* Stick in a forwarding pointer for the code object. */
869 *(lispobj *) code = result;
871 /* Put in forwarding pointers for all the functions. */
872 for (func = code->entry_points;
873 func != NIL; func = ((struct function *) PTR(func))->next) {
875 gc_assert(LowtagOf(func) == type_FunctionPointer);
877 *(lispobj *) PTR(func) = result + (func - thing);
880 /* Arrange to scavenge the debug info later. */
881 pscav_later(&new->debug_info, 1);
883 if (new->trace_table_offset & 0x3)
885 pscav(&new->trace_table_offset, 1, FALSE);
887 new->trace_table_offset = NIL; /* limit lifetime */
890 /* Scavenge the constants. */
891 pscav(new->constants, HeaderValue(new->header) - 5, TRUE);
893 /* Scavenge all the functions. */
894 pscav(&new->entry_points, 1, TRUE);
895 for (func = new->entry_points;
896 func != NIL; func = ((struct function *) PTR(func))->next) {
897 gc_assert(LowtagOf(func) == type_FunctionPointer);
898 gc_assert(!dynamic_pointer_p(func));
900 #if (defined(i386) || defined(__x86_64))
901 /* Temporarily convert the self pointer to a real function
903 ((struct function *) PTR(func))->self -= RAW_ADDR_OFFSET;
905 pscav(&((struct function *) PTR(func))->self, 2, TRUE);
906 #if (defined(i386) || defined(__x86_64))
907 ((struct function *) PTR(func))->self += RAW_ADDR_OFFSET;
909 pscav_later(&((struct function *) PTR(func))->name, 3);
916 ptrans_func(lispobj thing, lispobj header)
919 lispobj code, *new, *old, result;
920 struct function *function;
922 /* THING can either be a function header, a closure function header, */
923 /* a closure, or a funcallable-instance. If it's a closure or a */
924 /* funcallable-instance, we do the same as ptrans_boxed. */
925 /* Otherwise we have to do something strange, 'cause it is buried inside */
928 if (TypeOf(header) == type_FunctionHeader ||
929 TypeOf(header) == type_ClosureFunctionHeader) {
931 /* We can only end up here if the code object has not been */
932 /* scavenged, because if it had been scavenged, forwarding pointers */
933 /* would have been left behind for all the entry points. */
935 function = (struct function *) PTR(thing);
938 (HeaderValue(function->header) *
939 sizeof(lispobj))) | type_OtherPointer;
941 /* This will cause the function's header to be replaced with a */
942 /* forwarding pointer. */
945 /* So we can just return that. */
946 return function->header;
948 /* It's some kind of closure-like thing. */
949 nwords = 1 + HeaderValue(header);
950 old = (lispobj *) PTR(thing);
952 /* Allocate the new one. */
953 if (TypeOf(header) == type_FuncallableInstanceHeader) {
954 /* FINs *must* not go in read_only space. */
956 static_free += CEILING(nwords, 2);
957 assert_static_space_bounds(static_free);
959 /* Closures can always go in read-only space, 'caues */
960 /* they never change. */
962 new = read_only_free;
963 read_only_free += CEILING(nwords, 2);
964 assert_readonly_space_bounds(read_only_free);
967 memmove(new, old, nwords * sizeof(lispobj));
969 /* Deposit forwarding pointer. */
970 result = (lispobj) new | LowtagOf(thing);
974 pscav(new, nwords, FALSE);
981 ptrans_returnpc(lispobj thing, lispobj header)
985 /* Find the corresponding code object. */
986 code = thing - HeaderValue(header) * sizeof(lispobj);
988 /* Make sure it's been transported. */
989 new = *(lispobj *) PTR(code);
990 if (!forwarding_pointer_p(new))
991 new = ptrans_code(code);
993 /* Maintain the offset: */
994 return new + (thing - code);
997 #define WORDS_PER_CONS CEILING(sizeof(struct cons) / sizeof(lispobj), 2)
1000 ptrans_list(lispobj thing, boolean constant)
1002 struct cons *old, *new, *orig;
1006 orig = (struct cons *) read_only_free;
1008 orig = (struct cons *) static_free;
1012 /* Allocate a new cons cell. */
1013 old = (struct cons *) PTR(thing);
1015 new = (struct cons *) read_only_free;
1016 read_only_free += WORDS_PER_CONS;
1017 assert_readonly_space_bounds(read_only_free);
1019 new = (struct cons *) static_free;
1020 static_free += WORDS_PER_CONS;
1021 assert_static_space_bounds(static_free);
1024 /* Copy the cons cell and keep a pointer to the cdr. */
1025 new->car = old->car;
1026 thing = new->cdr = old->cdr;
1028 /* Set up the forwarding pointer. */
1029 *(lispobj *) old = ((lispobj) new) | type_ListPointer;
1031 /* And count this cell. */
1033 } while (LowtagOf(thing) == type_ListPointer &&
1034 dynamic_pointer_p(thing) &&
1035 !(forwarding_pointer_p(*(lispobj *) PTR(thing))));
1037 /* Scavenge the list we just copied. */
1038 pscav((lispobj *) orig, length * WORDS_PER_CONS, constant);
1040 return ((lispobj) orig) | type_ListPointer;
1044 ptrans_otherptr(lispobj thing, lispobj header, boolean constant)
1046 switch (TypeOf(header)) {
1048 case type_SingleFloat:
1049 case type_DoubleFloat:
1050 #ifdef type_LongFloat
1051 case type_LongFloat:
1053 #ifdef type_DoubleDoubleFloat
1054 case type_DoubleDoubleFloat:
1056 #ifdef type_ComplexSingleFloat
1057 case type_ComplexSingleFloat:
1059 #ifdef type_ComplexDoubleFloat
1060 case type_ComplexDoubleFloat:
1062 #ifdef type_ComplexLongFloat
1063 case type_ComplexLongFloat:
1065 #ifdef type_ComplexDoubleDoubleFloat
1066 case type_ComplexDoubleDoubleFloat:
1069 return ptrans_unboxed(thing, header);
1073 case type_SimpleArray:
1074 case type_ComplexString:
1075 case type_ComplexVector:
1076 case type_ComplexArray:
1077 return ptrans_boxed(thing, header, constant);
1079 case type_ValueCellHeader:
1080 case type_WeakPointer:
1081 #ifdef type_ScavengerHook
1082 case type_ScavengerHook:
1084 return ptrans_boxed(thing, header, FALSE);
1086 case type_SymbolHeader:
1087 return ptrans_boxed(thing, header, FALSE);
1089 case type_SimpleString:
1091 return ptrans_vector(thing, 8, 1, FALSE, constant);
1093 return ptrans_vector(thing, 16, 1, FALSE, constant);
1095 case type_SimpleBitVector:
1096 return ptrans_vector(thing, 1, 0, FALSE, constant);
1098 case type_SimpleVector:
1100 return ptrans_vector(thing, 64, 0, TRUE, constant);
1102 return ptrans_vector(thing, 32, 0, TRUE, constant);
1105 case type_SimpleArrayUnsignedByte2:
1106 return ptrans_vector(thing, 2, 0, FALSE, constant);
1108 case type_SimpleArrayUnsignedByte4:
1109 return ptrans_vector(thing, 4, 0, FALSE, constant);
1111 case type_SimpleArrayUnsignedByte8:
1112 #ifdef type_SimpleArraySignedByte8
1113 case type_SimpleArraySignedByte8:
1115 return ptrans_vector(thing, 8, 0, FALSE, constant);
1117 case type_SimpleArrayUnsignedByte16:
1118 #ifdef type_SimpleArraySignedByte16
1119 case type_SimpleArraySignedByte16:
1121 return ptrans_vector(thing, 16, 0, FALSE, constant);
1123 case type_SimpleArrayUnsignedByte32:
1124 #ifdef type_SimpleArraySignedByte30
1125 case type_SimpleArraySignedByte30:
1127 #ifdef type_SimpleArraySignedByte32
1128 case type_SimpleArraySignedByte32:
1130 return ptrans_vector(thing, 32, 0, FALSE, constant);
1132 case type_SimpleArraySingleFloat:
1133 return ptrans_vector(thing, 32, 0, FALSE, constant);
1135 case type_SimpleArrayDoubleFloat:
1136 return ptrans_vector(thing, 64, 0, FALSE, constant);
1138 #ifdef type_SimpleArrayLongFloat
1139 case type_SimpleArrayLongFloat:
1140 #if (defined(i386) || defined(__x86_64))
1141 return ptrans_vector(thing, 96, 0, FALSE, constant);
1144 return ptrans_vector(thing, 128, 0, FALSE, constant);
1148 #ifdef type_SimpleArrayDoubleDoubleFloat
1149 case type_SimpleArrayDoubleDoubleFloat:
1150 return ptrans_vector(thing, 128, 0, FALSE, constant);
1153 #ifdef type_SimpleArrayComplexSingleFloat
1154 case type_SimpleArrayComplexSingleFloat:
1155 return ptrans_vector(thing, 64, 0, FALSE, constant);
1158 #ifdef type_SimpleArrayComplexDoubleFloat
1159 case type_SimpleArrayComplexDoubleFloat:
1160 return ptrans_vector(thing, 128, 0, FALSE, constant);
1163 #ifdef type_SimpleArrayComplexLongFloat
1164 case type_SimpleArrayComplexLongFloat:
1165 #if (defined(i386) || defined(__x86_64))
1166 return ptrans_vector(thing, 192, 0, FALSE, constant);
1169 return ptrans_vector(thing, 256, 0, FALSE, constant);
1173 #ifdef type_SimpleArrayComplexDoubleDoubleFloat
1174 case type_SimpleArrayComplexDoubleDoubleFloat:
1175 return ptrans_vector(thing, 256, 0, FALSE, constant);
1179 case type_CodeHeader:
1180 return ptrans_code(thing);
1182 case type_ReturnPcHeader:
1183 return ptrans_returnpc(thing, header);
1186 return ptrans_fdefn(thing, header);
1189 /* Should only come across other pointers to the above stuff. */
1196 pscav_fdefn(struct fdefn *fdefn)
1201 ((char *) (fdefn->function + RAW_ADDR_OFFSET) == fdefn->raw_addr);
1202 pscav(&fdefn->name, 1, TRUE);
1203 pscav(&fdefn->function, 1, FALSE);
1205 fdefn->raw_addr = (char *) (fdefn->function + RAW_ADDR_OFFSET);
1206 return sizeof(struct fdefn) / sizeof(lispobj);
1209 #if (defined(i386) || defined(__x86_64))
1210 /* now putting code objects in static space */
1212 pscav_code(struct code *code)
1217 nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
1219 /* pw--The trace_table_offset slot can contain a list pointer. This
1220 * occurs when the code object is a top level form that initializes
1221 * a byte-compiled function. The fact that purify was ignoring this
1222 * slot may be a bug unrelated to the x86 port, except that TLF's
1223 * normally become unreachable after the loader calls them and
1224 * won't be seen by purify at all!!
1226 if (code->trace_table_offset & 0x3)
1228 pscav(&code->trace_table_offset, 1, FALSE);
1230 code->trace_table_offset = NIL; /* limit lifetime */
1233 /* Arrange to scavenge the debug info later. */
1234 pscav_later(&code->debug_info, 1);
1236 /* Scavenge the constants. */
1237 pscav(code->constants, HeaderValue(code->header) - 5, TRUE);
1239 /* Scavenge all the functions. */
1240 pscav(&code->entry_points, 1, TRUE);
1241 for (func = code->entry_points;
1242 func != NIL; func = ((struct function *) PTR(func))->next) {
1243 gc_assert(LowtagOf(func) == type_FunctionPointer);
1244 gc_assert(!dynamic_pointer_p(func));
1246 /* Temporarly convert the self pointer to a real function
1248 ((struct function *) PTR(func))->self -= RAW_ADDR_OFFSET;
1249 pscav(&((struct function *) PTR(func))->self, 2, TRUE);
1250 ((struct function *) PTR(func))->self += RAW_ADDR_OFFSET;
1251 pscav_later(&((struct function *) PTR(func))->name, 3);
1254 return CEILING(nwords, 2);
1258 #ifdef type_ScavengerHook
1259 static struct scavenger_hook *scavenger_hooks = (void *) NIL;
1262 pscav_scavenger_hook(struct scavenger_hook *scav_hook)
1264 lispobj old_value = scav_hook->value;
1266 /* Scavenge the value */
1267 pscav((lispobj *) scav_hook + 1, 1, FALSE);
1269 /* Did the value object move? */
1270 if (scav_hook->value != old_value) {
1271 /* Check if this hook is already noted. */
1272 if (scav_hook->next == NULL) {
1273 scav_hook->next = scavenger_hooks;
1275 (struct scavenger_hook *) ((unsigned long) scav_hook |
1280 /* Scavenge the function */
1281 pscav((lispobj *) scav_hook + 2, 1, FALSE);
1288 pscav(lispobj * addr, int nwords, boolean constant)
1290 lispobj thing, *thingp, header;
1292 struct vector *vector;
1294 while (nwords > 0) {
1296 if (Pointerp(thing)) {
1297 /* It's a pointer. Is it something we might have to move? */
1298 if (dynamic_pointer_p(thing)) {
1299 /* Maybe. Have we already moved it? */
1300 thingp = (lispobj *) PTR(thing);
1302 if (Pointerp(header) && forwarding_pointer_p(header))
1303 /* Yep, so just copy the forwarding pointer. */
1306 /* Nope, copy the object. */
1307 switch (LowtagOf(thing)) {
1308 case type_FunctionPointer:
1309 thing = ptrans_func(thing, header);
1312 case type_ListPointer:
1313 thing = ptrans_list(thing, constant);
1316 case type_InstancePointer:
1317 thing = ptrans_instance(thing, header, constant);
1320 case type_OtherPointer:
1321 thing = ptrans_otherptr(thing, header, constant);
1325 /* It was a pointer, but not one of them? */
1332 } else if (thing & 3) {
1333 /* It's an other immediate. Maybe the header for an unboxed */
1335 switch (TypeOf(thing)) {
1337 case type_SingleFloat:
1338 case type_DoubleFloat:
1339 #ifdef type_LongFloat
1340 case type_LongFloat:
1342 #ifdef type_DoubleDoubleFloat
1343 case type_DoubleDoubleFloat:
1346 /* It's an unboxed simple object. */
1347 count = HeaderValue(thing) + 1;
1350 case type_SimpleVector:
1351 if (HeaderValue(thing) == subtype_VectorValidHashing)
1352 *addr = (subtype_VectorMustRehash << type_Bits) |
1357 case type_SimpleString:
1358 vector = (struct vector *) addr;
1361 CEILING(NWORDS(fixnum_value(vector->length) + 1, 8) + 2,
1366 CEILING(NWORDS(fixnum_value(vector->length) + 1, 4) + 2,
1369 CEILING(NWORDS(fixnum_value(vector->length) + 1, 2) + 2,
1375 case type_SimpleBitVector:
1376 vector = (struct vector *) addr;
1379 CEILING(NWORDS(fixnum_value(vector->length), 64) + 2, 2);
1382 CEILING(NWORDS(fixnum_value(vector->length), 32) + 2, 2);
1386 case type_SimpleArrayUnsignedByte2:
1387 vector = (struct vector *) addr;
1390 CEILING(NWORDS(fixnum_value(vector->length), 32) + 2, 2);
1393 CEILING(NWORDS(fixnum_value(vector->length), 16) + 2, 2);
1397 case type_SimpleArrayUnsignedByte4:
1398 vector = (struct vector *) addr;
1401 CEILING(NWORDS(fixnum_value(vector->length), 16) + 2, 2);
1404 CEILING(NWORDS(fixnum_value(vector->length), 8) + 2, 2);
1408 case type_SimpleArrayUnsignedByte8:
1409 #ifdef type_SimpleArraySignedByte8
1410 case type_SimpleArraySignedByte8:
1412 vector = (struct vector *) addr;
1415 CEILING(NWORDS(fixnum_value(vector->length), 8) + 2, 2);
1418 CEILING(NWORDS(fixnum_value(vector->length), 4) + 2, 2);
1422 case type_SimpleArrayUnsignedByte16:
1423 #ifdef type_SimpleArraySignedByte16
1424 case type_SimpleArraySignedByte16:
1426 vector = (struct vector *) addr;
1429 CEILING(NWORDS(fixnum_value(vector->length), 4) + 2, 2);
1432 CEILING(NWORDS(fixnum_value(vector->length), 2) + 2, 2);
1436 case type_SimpleArrayUnsignedByte32:
1437 #ifdef type_SimpleArraySignedByte30
1438 case type_SimpleArraySignedByte30:
1440 #ifdef type_SimpleArraySignedByte32
1441 case type_SimpleArraySignedByte32:
1443 vector = (struct vector *) addr;
1446 CEILING(NWORDS(fixnum_value(vector->length), 2) + 2, 2);
1448 count = CEILING(fixnum_value(vector->length) + 2, 2);
1452 case type_SimpleArraySingleFloat:
1453 vector = (struct vector *) addr;
1456 CEILING(NWORDS(fixnum_value(vector->length), 2) + 2, 2);
1458 count = CEILING(fixnum_value(vector->length) + 2, 2);
1462 case type_SimpleArrayDoubleFloat:
1463 #ifdef type_SimpleArrayComplexSingleFloat
1464 case type_SimpleArrayComplexSingleFloat:
1466 vector = (struct vector *) addr;
1468 count = CEILING(fixnum_value(vector->length) + 2, 2);
1470 count = fixnum_value(vector->length) * 2 + 2;
1474 #ifdef type_SimpleArrayLongFloat
1475 case type_SimpleArrayLongFloat:
1476 vector = (struct vector *) addr;
1478 count = fixnum_value(vector->length) * 3 + 2;
1481 count = fixnum_value(vector->length) * 2 + 2;
1484 count = fixnum_value(vector->length) * 4 + 2;
1489 #ifdef type_SimpleArrayComplexDoubleFloat
1490 case type_SimpleArrayComplexDoubleFloat:
1491 vector = (struct vector *) addr;
1493 count = fixnum_value(vector->length) * 2 + 2;
1495 count = fixnum_value(vector->length) * 4 + 2;
1500 #ifdef type_SimpleArrayComplexLongFloat
1501 case type_SimpleArrayComplexLongFloat:
1502 vector = (struct vector *) addr;
1504 count = fixnum_value(vector->length) * 6 + 2;
1507 count = fixnum_value(vector->length) * 4 + 2;
1510 count = fixnum_value(vector->length) * 8 + 2;
1515 #ifdef type_SimpleArrayComplexDoubleDoubleFloat
1516 case type_SimpleArrayComplexDoubleDoubleFloat:
1517 vector = (struct vector *) addr;
1518 count = fixnum_value(vector->length) * 8 + 2;
1522 case type_CodeHeader:
1523 #if !(defined(i386) || defined(__x86_64))
1524 gc_abort(); /* No code headers in static space */
1526 count = pscav_code((struct code *) addr);
1530 case type_FunctionHeader:
1531 case type_ClosureFunctionHeader:
1532 case type_ReturnPcHeader:
1533 /* We should never hit any of these, 'cause they occur */
1534 /* buried in the middle of code objects. */
1541 #if (defined(i386) || defined(__x86_64))
1542 case type_ClosureHeader:
1543 case type_FuncallableInstanceHeader:
1544 case type_ByteCodeFunction:
1545 case type_ByteCodeClosure:
1546 #ifdef type_DylanFunctionHeader
1547 case type_DylanFunctionHeader:
1549 /* The function self pointer needs special care on the
1550 x86 because it is the real entry point. */
1552 lispobj fun = ((struct closure *) addr)->function
1555 pscav(&fun, 1, constant);
1556 ((struct closure *) addr)->function = fun + RAW_ADDR_OFFSET;
1562 case type_WeakPointer:
1563 /* Weak pointers get preserved during purify, 'cause I don't */
1564 /* feel like figuring out how to break them. */
1565 pscav(addr + 1, 2, constant);
1570 /* We have to handle fdefn objects specially, so we can fix */
1571 /* up the raw function address. */
1572 count = pscav_fdefn((struct fdefn *) addr);
1575 #ifdef type_ScavengerHook
1576 case type_ScavengerHook:
1577 count = pscav_scavenger_hook((struct scavenger_hook *) addr);
1586 /* It's a fixnum. */
1598 purify(lispobj static_roots, lispobj read_only_roots)
1602 struct later *laters, *next;
1605 printf("[Doing purification:");
1609 if (fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX)) != 0) {
1610 printf(" Ack! Can't purify interrupt contexts. ");
1614 #if defined(ibmrt) || defined(i386) || defined(__x86_64)
1615 current_dynamic_space_free_pointer =
1616 (lispobj *) SymbolValue(ALLOCATION_POINTER);
1619 read_only_end = read_only_free =
1620 (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER);
1621 static_end = static_free =
1622 (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER);
1630 #if (defined(i386) || defined(__x86_64))
1631 gc_assert(control_stack_end > ((&read_only_roots) + 1));
1632 setup_i386_stack_scav(((&static_roots) - 2), control_stack_end);
1633 #elif defined(sparc)
1637 pscav(&static_roots, 1, FALSE);
1638 pscav(&read_only_roots, 1, TRUE);
1641 printf(" handlers");
1644 pscav((lispobj *) interrupt_handlers,
1645 sizeof(interrupt_handlers) / sizeof(lispobj), FALSE);
1651 #if !(defined(i386) || defined(__x86_64))
1652 pscav(control_stack, current_control_stack_pointer - control_stack, FALSE);
1658 gc_assert(control_stack_end > ((&read_only_roots) + 1));
1659 carefully_pscav_stack(((&read_only_roots) + 1), control_stack_end);
1664 printf(" bindings");
1667 #if !defined(ibmrt) && !defined(i386) && !defined(__x86_64)
1668 pscav(binding_stack, current_binding_stack_pointer - binding_stack, FALSE);
1670 pscav(binding_stack,
1671 (lispobj *) SymbolValue(BINDING_STACK_POINTER) - binding_stack,
1675 #ifdef SCAVENGE_READ_ONLY_SPACE
1676 if (SymbolValue(SCAVENGE_READ_ONLY_SPACE) != type_UnboundMarker
1677 && SymbolValue(SCAVENGE_READ_ONLY_SPACE) != NIL) {
1678 unsigned read_only_space_size =
1679 (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER) -
1682 fprintf(stderr, "Scavenge read only space: %lu bytes\n",
1683 (unsigned long) (read_only_space_size * sizeof(lispobj)));
1684 pscav(read_only_space, read_only_space_size, FALSE);
1692 clean = static_space;
1694 while (clean < static_free)
1695 clean = pscav(clean, static_free - clean, FALSE);
1696 if (clean != static_free) {
1697 fprintf(stderr, "*** clean (%p) != static_free (%p)\n",
1698 clean, static_free);
1699 fprintf(stderr, " Possible heap corruption?\n");
1702 laters = later_blocks;
1703 count = later_count;
1704 later_blocks = NULL;
1706 while (laters != NULL) {
1707 for (i = 0; i < count; i++) {
1708 if (laters->u[i].count == 0);
1709 else if (laters->u[i].count <= LATERMAXCOUNT) {
1710 pscav(laters->u[i + 1].ptr, laters->u[i].count, TRUE);
1713 pscav(laters->u[i].ptr, 1, TRUE);
1715 next = laters->next;
1718 count = LATERBLOCKSIZE;
1720 } while (clean < static_free || later_blocks != NULL);
1722 if (clean != static_free) {
1723 fprintf(stderr, "*** clean (%p) != static_free (%p)\n",
1724 clean, static_free);
1725 fprintf(stderr, " Possible heap corruption?\n");
1735 #if defined(WANT_CGC) && defined(X86_CGC_ACTIVE_P)
1736 if (SymbolValue(X86_CGC_ACTIVE_P) != T)
1737 os_zero((os_vm_address_t) current_dynamic_space,
1738 (os_vm_size_t) dynamic_space_size);
1740 #if !defined(GENCGC)
1741 os_zero((os_vm_address_t) current_dynamic_space,
1742 (os_vm_size_t) dynamic_space_size);
1747 * Zero stack. Note the stack is also zeroed by sub-gc calling
1748 * scrub-control-stack - this zeros the stack on the x86.
1750 #if !(defined(i386) || defined(__x86_64))
1751 os_zero((os_vm_address_t) current_control_stack_pointer,
1752 (os_vm_size_t) (control_stack_size -
1753 ((current_control_stack_pointer - control_stack) *
1757 #if defined(WANT_CGC) && defined(STATIC_BLUE_BAG)
1759 lispobj bag = SymbolValue(STATIC_BLUE_BAG);
1760 struct cons *cons = (struct cons *) static_free;
1761 struct cons *pair = cons + 1;
1763 static_free += 2 * WORDS_PER_CONS;
1764 if (bag == type_UnboundMarker)
1767 cons->car = (lispobj) pair | type_ListPointer;
1768 pair->car = (lispobj) static_end;
1769 pair->cdr = (lispobj) static_free;
1770 bag = (lispobj) cons | type_ListPointer;
1771 SetSymbolValue(STATIC_BLUE_BAG, bag);
1776 * It helps to update the heap free pointers so that free_heap can
1777 * verify after it's done.
1779 SetSymbolValue(READ_ONLY_SPACE_FREE_POINTER, (lispobj) read_only_free);
1780 SetSymbolValue(STATIC_SPACE_FREE_POINTER, (lispobj) static_free);
1784 * Test the static space for validity. This was useful in
1785 * catching some corruption problems on x86. Should we enable
1786 * this all the time?
1788 verify_space((lispobj *) static_space, static_free - static_space);
1791 #if !defined(ibmrt) && !defined(i386) && !defined(__x86_64) && !((defined(sparc) || (defined(DARWIN) && defined(__ppc__))) && defined(GENCGC))
1792 current_dynamic_space_free_pointer = current_dynamic_space;
1794 #if defined(WANT_CGC) && defined(X86_CGC_ACTIVE_P)
1796 if (SymbolValue(X86_CGC_ACTIVE_P) != T)
1797 SetSymbolValue(ALLOCATION_POINTER, (lispobj) current_dynamic_space);
1804 /* ibmrt using GC */
1805 SetSymbolValue(ALLOCATION_POINTER, (lispobj) current_dynamic_space);
1810 #ifdef type_ScavengerHook
1811 /* Call the scavenger hook functions */
1813 struct scavenger_hook *sh;
1815 for (sh = (struct scavenger_hook *) PTR((int) scavenger_hooks);
1816 (lispobj) sh != PTR(NIL);) {
1817 struct scavenger_hook *sh_next =
1818 (struct scavenger_hook *) PTR((unsigned long) sh->next);
1820 funcall0(sh->function);
1824 scavenger_hooks = (struct scavenger_hook *) NIL;
1829 printf(" Done.]\n");