2b4c72d9e0d5c36fa5716ce720e46e950bf31731
[sbcl.git] / src / runtime / purify.c
1 /*
2  * C-level stuff to implement Lisp-level PURIFY
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <stdlib.h>
19
20 #include "runtime.h"
21 #include "os.h"
22 #include "sbcl.h"
23 #include "globals.h"
24 #include "validate.h"
25 #include "interrupt.h"
26 #include "purify.h"
27 #include "interr.h"
28 #ifdef GENCGC
29 #include "gencgc.h"
30 #endif
31
32 #define PRINTNOISE
33
34 #if defined(ibmrt) || defined(__i386__)
35 /* again, what's so special about the x86 that this is differently
36  * visible there than on other platforms? -dan 20010125 
37  */
38 static lispobj *dynamic_space_free_pointer;
39 #endif
40
41 #define gc_abort() \
42   lose("GC invariant lost, file \"%s\", line %d", __FILE__, __LINE__)
43
44 #if 1
45 #define gc_assert(ex) do { \
46         if (!(ex)) gc_abort(); \
47 } while (0)
48 #else
49 #define gc_assert(ex)
50 #endif
51
52 \f
53 /* These hold the original end of the read_only and static spaces so
54  * we can tell what are forwarding pointers. */
55
56 static lispobj *read_only_end, *static_end;
57
58 static lispobj *read_only_free, *static_free;
59
60 static lispobj *pscav(lispobj *addr, int nwords, boolean constant);
61
62 #define LATERBLOCKSIZE 1020
63 #define LATERMAXCOUNT 10
64
65 static struct later {
66     struct later *next;
67     union {
68         lispobj *ptr;
69         int count;
70     } u[LATERBLOCKSIZE];
71 } *later_blocks = NULL;
72 static int later_count = 0;
73
74 #define CEILING(x,y) (((x) + ((y) - 1)) & (~((y) - 1)))
75 #define NWORDS(x,y) (CEILING((x),(y)) / (y))
76
77 #ifdef sparc
78 #define RAW_ADDR_OFFSET 0
79 #else
80 #define RAW_ADDR_OFFSET (6*sizeof(lispobj) - type_FunctionPointer)
81 #endif
82 \f
83 static boolean
84 forwarding_pointer_p(lispobj obj)
85 {
86     lispobj *ptr;
87
88     ptr = (lispobj *)obj;
89
90     return ((static_end <= ptr && ptr <= static_free) ||
91             (read_only_end <= ptr && ptr <= read_only_free));
92 }
93
94 static boolean
95 dynamic_pointer_p(lispobj ptr)
96 {
97 #ifndef __i386__
98     /* KLUDGE: This has an implicit dependence on the ordering of
99      * address spaces, and is therefore basically wrong. I'd fix it,
100      * but I don't have a non-386 port to test it on. Porters are
101      * encouraged to fix it. -- WHN 2000-10-17 */
102     return (ptr >= (lispobj)DYNAMIC_SPACE_START);
103 #else
104     /* Be more conservative, and remember, this is a maybe. */
105     return (ptr >= (lispobj)DYNAMIC_SPACE_START
106             &&
107             ptr < (lispobj)dynamic_space_free_pointer);
108 #endif
109 }
110
111 \f
112 #ifdef __i386__
113
114 #ifdef WANT_CGC
115 /* original x86/CGC stack scavenging code by Paul Werkowski */
116
117 static int
118 maybe_can_move_p(lispobj thing)
119 {
120   lispobj *thingp,header;
121   if (dynamic_pointer_p(thing)) { /* in dynamic space */
122     thingp = (lispobj*)PTR(thing);
123     header = *thingp;
124     if(Pointerp(header) && forwarding_pointer_p(header))
125       return -1;                /* must change it */
126     if(LowtagOf(thing) == type_ListPointer)
127       return type_ListPointer;  /* can we check this somehow */
128     else if (thing & 3) {       /* not fixnum */
129       int kind = TypeOf(header);
130       /* printf(" %x %x",header,kind); */
131       switch (kind) {           /* something with a header */
132       case type_Bignum:
133       case type_SingleFloat:
134       case type_DoubleFloat:
135 #ifdef type_LongFloat
136       case type_LongFloat:
137 #endif
138       case type_Sap:
139       case type_SimpleVector:
140       case type_SimpleString:
141       case type_SimpleBitVector:
142       case type_SimpleArrayUnsignedByte2:
143       case type_SimpleArrayUnsignedByte4:
144       case type_SimpleArrayUnsignedByte8:
145       case type_SimpleArrayUnsignedByte16:
146       case type_SimpleArrayUnsignedByte32:
147 #ifdef type_SimpleArraySignedByte8
148       case type_SimpleArraySignedByte8:
149 #endif
150 #ifdef type_SimpleArraySignedByte16
151       case type_SimpleArraySignedByte16:
152 #endif
153 #ifdef type_SimpleArraySignedByte30
154       case type_SimpleArraySignedByte30:
155 #endif
156 #ifdef type_SimpleArraySignedByte32
157       case type_SimpleArraySignedByte32:
158 #endif
159       case type_SimpleArraySingleFloat:
160       case type_SimpleArrayDoubleFloat:
161 #ifdef type_SimpleArrayLongFloat
162       case type_SimpleArrayLongFloat:
163 #endif
164 #ifdef type_SimpleArrayComplexSingleFloat
165       case type_SimpleArrayComplexSingleFloat:
166 #endif
167 #ifdef type_SimpleArrayComplexDoubleFloat
168       case type_SimpleArrayComplexDoubleFloat:
169 #endif
170 #ifdef type_SimpleArrayComplexLongFloat
171       case type_SimpleArrayComplexLongFloat:
172 #endif
173       case type_CodeHeader:
174       case type_FunctionHeader:
175       case type_ClosureFunctionHeader:
176       case type_ReturnPcHeader:
177       case type_ClosureHeader:
178       case type_FuncallableInstanceHeader:
179       case type_InstanceHeader:
180       case type_ValueCellHeader:
181       case type_ByteCodeFunction:
182       case type_ByteCodeClosure:
183       case type_WeakPointer:
184       case type_Fdefn:
185         return kind;
186         break;
187       default:
188         return 0;
189       }}}
190   return 0;
191 }
192
193 static int pverbose=0;
194 #define PVERBOSE pverbose
195 static void
196 carefully_pscav_stack(lispobj*lowaddr, lispobj*base)
197 {
198   lispobj*sp = lowaddr;
199   while (sp < base)
200     { int k;
201       lispobj thing = *sp;
202       if((unsigned)thing & 0x3) /* may be pointer */
203         {
204           /* need to check for valid float/double? */
205           k = maybe_can_move_p(thing);
206           if(PVERBOSE)printf("%8x %8x %d\n",sp, thing, k);
207           if(k)
208             pscav(sp, 1, 0);
209         }
210       sp++;
211     }
212 }
213 #endif
214
215 #ifdef GENCGC
216 /*
217  * Enhanced x86/GENCGC stack scavenging by Douglas Crosher.
218  *
219  * Scavenging the stack on the i386 is problematic due to conservative
220  * roots and raw return addresses. Here it is handled in two passes:
221  * the first pass runs before any objects are moved and tries to
222  * identify valid pointers and return address on the stack, the second
223  * pass scavenges these.
224  */
225
226 static unsigned pointer_filter_verbose = 0;
227
228 static int
229 valid_dynamic_space_pointer(lispobj *pointer, lispobj *start_addr)
230 {
231   /* If it's not a return address then it needs to be a valid Lisp
232    * pointer. */
233   if (!Pointerp((lispobj)pointer))
234     return 0;
235
236   /* Check that the object pointed to is consistent with the pointer
237    * low tag. */
238   switch (LowtagOf((lispobj)pointer)) {
239   case type_FunctionPointer:
240     /* Start_addr should be the enclosing code object, or a closure
241      * header. */
242     switch (TypeOf(*start_addr)) {
243     case type_CodeHeader:
244       /* This case is probably caught above. */
245       break;
246     case type_ClosureHeader:
247     case type_FuncallableInstanceHeader:
248     case type_ByteCodeFunction:
249     case type_ByteCodeClosure:
250       if ((int)pointer != ((int)start_addr+type_FunctionPointer)) {
251         if (pointer_filter_verbose) {
252           fprintf(stderr,"*Wf2: %x %x %x\n", (unsigned int) pointer, 
253                   (unsigned int) start_addr, *start_addr);
254         }
255         return 0;
256       }
257       break;
258     default:
259       if (pointer_filter_verbose) {
260         fprintf(stderr,"*Wf3: %x %x %x\n", (unsigned int) pointer, 
261                 (unsigned int) start_addr, *start_addr);
262       }
263       return 0;
264     }
265     break;
266   case type_ListPointer:
267     if ((int)pointer != ((int)start_addr+type_ListPointer)) {
268       if (pointer_filter_verbose)
269         fprintf(stderr,"*Wl1: %x %x %x\n", (unsigned int) pointer, 
270                 (unsigned int) start_addr, *start_addr);
271       return 0;
272     }
273     /* Is it plausible cons? */
274     if((Pointerp(start_addr[0])
275         || ((start_addr[0] & 3) == 0) /* fixnum */
276         || (TypeOf(start_addr[0]) == type_BaseChar)
277         || (TypeOf(start_addr[0]) == type_UnboundMarker))
278        && (Pointerp(start_addr[1])
279            || ((start_addr[1] & 3) == 0) /* fixnum */
280            || (TypeOf(start_addr[1]) == type_BaseChar)
281            || (TypeOf(start_addr[1]) == type_UnboundMarker))) {
282       break;
283     } else {
284       if (pointer_filter_verbose) {
285         fprintf(stderr,"*Wl2: %x %x %x\n", (unsigned int) pointer, 
286                 (unsigned int) start_addr, *start_addr);
287       }
288       return 0;
289     }
290   case type_InstancePointer:
291     if ((int)pointer != ((int)start_addr+type_InstancePointer)) {
292       if (pointer_filter_verbose) {
293         fprintf(stderr,"*Wi1: %x %x %x\n", (unsigned int) pointer, 
294                 (unsigned int) start_addr, *start_addr);
295       }
296       return 0;
297     }
298     if (TypeOf(start_addr[0]) != type_InstanceHeader) {
299       if (pointer_filter_verbose) {
300         fprintf(stderr,"*Wi2: %x %x %x\n", (unsigned int) pointer, 
301                 (unsigned int) start_addr, *start_addr);
302       }
303       return 0;
304     }
305     break;
306   case type_OtherPointer:
307     if ((int)pointer != ((int)start_addr+type_OtherPointer)) {
308       if (pointer_filter_verbose) {
309         fprintf(stderr,"*Wo1: %x %x %x\n", (unsigned int) pointer, 
310                 (unsigned int) start_addr, *start_addr);
311       }
312       return 0;
313     }
314     /* Is it plausible?  Not a cons. X should check the headers. */
315     if(Pointerp(start_addr[0]) || ((start_addr[0] & 3) == 0)) {
316       if (pointer_filter_verbose) {
317         fprintf(stderr,"*Wo2: %x %x %x\n", (unsigned int) pointer, 
318                 (unsigned int) start_addr, *start_addr);
319       }
320       return 0;
321     }
322     switch (TypeOf(start_addr[0])) {
323     case type_UnboundMarker:
324     case type_BaseChar:
325       if (pointer_filter_verbose) {
326         fprintf(stderr,"*Wo3: %x %x %x\n", (unsigned int) pointer, 
327                 (unsigned int) start_addr, *start_addr);
328       }
329       return 0;
330
331       /* only pointed to by function pointers? */
332     case type_ClosureHeader:
333     case type_FuncallableInstanceHeader:
334     case type_ByteCodeFunction:
335     case type_ByteCodeClosure:
336       if (pointer_filter_verbose) {
337         fprintf(stderr,"*Wo4: %x %x %x\n", (unsigned int) pointer, 
338                 (unsigned int) start_addr, *start_addr);
339       }
340       return 0;
341
342     case type_InstanceHeader:
343       if (pointer_filter_verbose) {
344         fprintf(stderr,"*Wo5: %x %x %x\n", (unsigned int) pointer, 
345                 (unsigned int) start_addr, *start_addr);
346       }
347       return 0;
348
349       /* the valid other immediate pointer objects */
350     case type_SimpleVector:
351     case type_Ratio:
352     case type_Complex:
353 #ifdef type_ComplexSingleFloat
354     case type_ComplexSingleFloat:
355 #endif
356 #ifdef type_ComplexDoubleFloat
357     case type_ComplexDoubleFloat:
358 #endif
359 #ifdef type_ComplexLongFloat
360     case type_ComplexLongFloat:
361 #endif
362     case type_SimpleArray:
363     case type_ComplexString:
364     case type_ComplexBitVector:
365     case type_ComplexVector:
366     case type_ComplexArray:
367     case type_ValueCellHeader:
368     case type_SymbolHeader:
369     case type_Fdefn:
370     case type_CodeHeader:
371     case type_Bignum:
372     case type_SingleFloat:
373     case type_DoubleFloat:
374 #ifdef type_LongFloat
375     case type_LongFloat:
376 #endif
377     case type_SimpleString:
378     case type_SimpleBitVector:
379     case type_SimpleArrayUnsignedByte2:
380     case type_SimpleArrayUnsignedByte4:
381     case type_SimpleArrayUnsignedByte8:
382     case type_SimpleArrayUnsignedByte16:
383     case type_SimpleArrayUnsignedByte32:
384 #ifdef type_SimpleArraySignedByte8
385     case type_SimpleArraySignedByte8:
386 #endif
387 #ifdef type_SimpleArraySignedByte16
388     case type_SimpleArraySignedByte16:
389 #endif
390 #ifdef type_SimpleArraySignedByte30
391     case type_SimpleArraySignedByte30:
392 #endif
393 #ifdef type_SimpleArraySignedByte32
394     case type_SimpleArraySignedByte32:
395 #endif
396     case type_SimpleArraySingleFloat:
397     case type_SimpleArrayDoubleFloat:
398 #ifdef type_SimpleArrayLongFloat
399     case type_SimpleArrayLongFloat:
400 #endif
401 #ifdef type_SimpleArrayComplexSingleFloat
402     case type_SimpleArrayComplexSingleFloat:
403 #endif
404 #ifdef type_SimpleArrayComplexDoubleFloat
405     case type_SimpleArrayComplexDoubleFloat:
406 #endif
407 #ifdef type_SimpleArrayComplexLongFloat
408     case type_SimpleArrayComplexLongFloat:
409 #endif
410     case type_Sap:
411     case type_WeakPointer:
412       break;
413
414     default:
415       if (pointer_filter_verbose) {
416         fprintf(stderr,"*Wo6: %x %x %x\n", (unsigned int) pointer, 
417                 (unsigned int) start_addr, *start_addr);
418       }
419       return 0;
420     }
421     break;
422   default:
423     if (pointer_filter_verbose) {
424       fprintf(stderr,"*W?: %x %x %x\n", (unsigned int) pointer, 
425               (unsigned int) start_addr, *start_addr);
426     }
427     return 0;
428   }
429
430   /* looks good */
431   return 1;
432 }
433
434 #define MAX_STACK_POINTERS 256
435 lispobj *valid_stack_locations[MAX_STACK_POINTERS];
436 unsigned int num_valid_stack_locations;
437
438 #define MAX_STACK_RETURN_ADDRESSES 128
439 lispobj *valid_stack_ra_locations[MAX_STACK_RETURN_ADDRESSES];
440 lispobj *valid_stack_ra_code_objects[MAX_STACK_RETURN_ADDRESSES];
441 unsigned int num_valid_stack_ra_locations;
442
443 /* Identify valid stack slots. */
444 static void
445 setup_i386_stack_scav(lispobj *lowaddr, lispobj *base)
446 {
447   lispobj *sp = lowaddr;
448   num_valid_stack_locations = 0;
449   num_valid_stack_ra_locations = 0;
450   for (sp = lowaddr; sp < base; sp++) {
451     lispobj thing = *sp;
452     /* Find the object start address */
453     lispobj *start_addr = search_dynamic_space((void *)thing);
454     if (start_addr) {
455       /* We need to allow raw pointers into Code objects for return
456        * addresses. This will also pick up pointers to functions in code
457        * objects. */
458       if (TypeOf(*start_addr) == type_CodeHeader) {
459         gc_assert(num_valid_stack_ra_locations < MAX_STACK_RETURN_ADDRESSES);
460         valid_stack_ra_locations[num_valid_stack_ra_locations] = sp;
461         valid_stack_ra_code_objects[num_valid_stack_ra_locations++] =
462           (lispobj *)((int)start_addr + type_OtherPointer);
463       } else {
464         if (valid_dynamic_space_pointer((void *)thing, start_addr)) {
465           gc_assert(num_valid_stack_locations < MAX_STACK_POINTERS);
466           valid_stack_locations[num_valid_stack_locations++] = sp;
467         }
468       }
469     }
470   }
471   if (pointer_filter_verbose) {
472     fprintf(stderr, "number of valid stack pointers = %d\n",
473             num_valid_stack_locations);
474     fprintf(stderr, "number of stack return addresses = %d\n",
475             num_valid_stack_ra_locations);
476   }
477 }
478
479 static void
480 pscav_i386_stack(void)
481 {
482   int i;
483
484   for (i = 0; i < num_valid_stack_locations; i++)
485     pscav(valid_stack_locations[i], 1, 0);
486
487   for (i = 0; i < num_valid_stack_ra_locations; i++) {
488     lispobj code_obj = (lispobj)valid_stack_ra_code_objects[i];
489     pscav(&code_obj, 1, 0);
490     if (pointer_filter_verbose) {
491       fprintf(stderr,"*C moved RA %x to %x; for code object %x to %x\n",
492               *valid_stack_ra_locations[i],
493               (int)(*valid_stack_ra_locations[i])
494               - ((int)valid_stack_ra_code_objects[i] - (int)code_obj),
495               (unsigned int) valid_stack_ra_code_objects[i], code_obj);
496     }
497     *valid_stack_ra_locations[i] =
498       ((int)(*valid_stack_ra_locations[i])
499        - ((int)valid_stack_ra_code_objects[i] - (int)code_obj));
500   }
501 }
502 #endif
503 #endif
504
505 \f
506 static void
507 pscav_later(lispobj *where, int count)
508 {
509     struct later *new;
510
511     if (count > LATERMAXCOUNT) {
512         while (count > LATERMAXCOUNT) {
513             pscav_later(where, LATERMAXCOUNT);
514             count -= LATERMAXCOUNT;
515             where += LATERMAXCOUNT;
516         }
517     }
518     else {
519         if (later_blocks == NULL || later_count == LATERBLOCKSIZE ||
520             (later_count == LATERBLOCKSIZE-1 && count > 1)) {
521             new  = (struct later *)malloc(sizeof(struct later));
522             new->next = later_blocks;
523             if (later_blocks && later_count < LATERBLOCKSIZE)
524                 later_blocks->u[later_count].ptr = NULL;
525             later_blocks = new;
526             later_count = 0;
527         }
528
529         if (count != 1)
530             later_blocks->u[later_count++].count = count;
531         later_blocks->u[later_count++].ptr = where;
532     }
533 }
534
535 static lispobj ptrans_boxed(lispobj thing, lispobj header, boolean constant)
536 {
537     int nwords;
538     lispobj result, *new, *old;
539
540     nwords = 1 + HeaderValue(header);
541
542     /* Allocate it */
543     old = (lispobj *)PTR(thing);
544     if (constant) {
545         new = read_only_free;
546         read_only_free += CEILING(nwords, 2);
547     }
548     else {
549         new = static_free;
550         static_free += CEILING(nwords, 2);
551     }
552
553     /* Copy it. */
554     bcopy(old, new, nwords * sizeof(lispobj));
555
556     /* Deposit forwarding pointer. */
557     result = (lispobj)new | LowtagOf(thing);
558     *old = result;
559
560     /* Scavenge it. */
561     pscav(new, nwords, constant);
562
563     return result;
564 }
565
566 /* We need to look at the layout to see whether it is a pure structure
567  * class, and only then can we transport as constant. If it is pure, we can
568  * ALWAYS transport as a constant. */
569 static lispobj ptrans_instance(lispobj thing, lispobj header, boolean constant)
570 {
571     lispobj layout = ((struct instance *)PTR(thing))->slots[0];
572     lispobj pure = ((struct instance *)PTR(layout))->slots[15];
573
574     switch (pure) {
575     case T:
576         return (ptrans_boxed(thing, header, 1));
577     case NIL:
578         return (ptrans_boxed(thing, header, 0));
579     case 0:
580         {
581             /* Substructure: special case for the COMPACT-INFO-ENVs, where
582              * the instance may have a point to the dynamic space placed
583              * into it (e.g. the cache-name slot), but the lists and arrays
584              * at the time of a purify can be moved to the RO space. */
585             int nwords;
586             lispobj result, *new, *old;
587
588             nwords = 1 + HeaderValue(header);
589
590             /* Allocate it */
591             old = (lispobj *)PTR(thing);
592             new = static_free;
593             static_free += CEILING(nwords, 2);
594
595             /* Copy it. */
596             bcopy(old, new, nwords * sizeof(lispobj));
597
598             /* Deposit forwarding pointer. */
599             result = (lispobj)new | LowtagOf(thing);
600             *old = result;
601
602             /* Scavenge it. */
603             pscav(new, nwords, 1);
604
605             return result;
606         }
607     default:
608         gc_abort();
609         return NIL; /* dummy value: return something ... */
610     }
611 }
612
613 static lispobj ptrans_fdefn(lispobj thing, lispobj header)
614 {
615     int nwords;
616     lispobj result, *new, *old, oldfn;
617     struct fdefn *fdefn;
618
619     nwords = 1 + HeaderValue(header);
620
621     /* Allocate it */
622     old = (lispobj *)PTR(thing);
623     new = static_free;
624     static_free += CEILING(nwords, 2);
625
626     /* Copy it. */
627     bcopy(old, new, nwords * sizeof(lispobj));
628
629     /* Deposit forwarding pointer. */
630     result = (lispobj)new | LowtagOf(thing);
631     *old = result;
632
633     /* Scavenge the function. */
634     fdefn = (struct fdefn *)new;
635     oldfn = fdefn->function;
636     pscav(&fdefn->function, 1, 0);
637     if ((char *)oldfn + RAW_ADDR_OFFSET == fdefn->raw_addr)
638         fdefn->raw_addr = (char *)fdefn->function + RAW_ADDR_OFFSET;
639
640     return result;
641 }
642
643 static lispobj ptrans_unboxed(lispobj thing, lispobj header)
644 {
645     int nwords;
646     lispobj result, *new, *old;
647
648     nwords = 1 + HeaderValue(header);
649
650     /* Allocate it */
651     old = (lispobj *)PTR(thing);
652     new = read_only_free;
653     read_only_free += CEILING(nwords, 2);
654
655     /* Copy it. */
656     bcopy(old, new, nwords * sizeof(lispobj));
657
658     /* Deposit forwarding pointer. */
659     result = (lispobj)new | LowtagOf(thing);
660     *old = result;
661
662     return result;
663 }
664
665 static lispobj ptrans_vector(lispobj thing, int bits, int extra,
666                              boolean boxed, boolean constant)
667 {
668     struct vector *vector;
669     int nwords;
670     lispobj result, *new;
671
672     vector = (struct vector *)PTR(thing);
673     nwords = 2 + (CEILING((fixnum_value(vector->length)+extra)*bits,32)>>5);
674
675     if (boxed && !constant) {
676         new = static_free;
677         static_free += CEILING(nwords, 2);
678     }
679     else {
680         new = read_only_free;
681         read_only_free += CEILING(nwords, 2);
682     }
683
684     bcopy(vector, new, nwords * sizeof(lispobj));
685
686     result = (lispobj)new | LowtagOf(thing);
687     vector->header = result;
688
689     if (boxed)
690         pscav(new, nwords, constant);
691
692     return result;
693 }
694
695 #ifdef __i386__
696 static void
697 apply_code_fixups_during_purify(struct code *old_code, struct code *new_code)
698 {
699   int nheader_words, ncode_words, nwords;
700   void  *constants_start_addr, *constants_end_addr;
701   void  *code_start_addr, *code_end_addr;
702   lispobj fixups = NIL;
703   unsigned  displacement = (unsigned)new_code - (unsigned)old_code;
704   struct vector *fixups_vector;
705
706   /* Byte compiled code has no fixups. The trace table offset will be
707    * a fixnum if it's x86 compiled code - check. */
708   if (new_code->trace_table_offset & 0x3)
709     return;
710
711   /* Else it's x86 machine code. */
712   ncode_words = fixnum_value(new_code->code_size);
713   nheader_words = HeaderValue(*(lispobj *)new_code);
714   nwords = ncode_words + nheader_words;
715
716   constants_start_addr = (void *)new_code + 5*4;
717   constants_end_addr = (void *)new_code + nheader_words*4;
718   code_start_addr = (void *)new_code + nheader_words*4;
719   code_end_addr = (void *)new_code + nwords*4;
720
721   /* The first constant should be a pointer to the fixups for this
722    * code objects. Check. */
723   fixups = new_code->constants[0];
724
725   /* It will be 0 or the unbound-marker if there are no fixups, and
726    * will be an other-pointer to a vector if it is valid. */
727   if ((fixups==0) || (fixups==type_UnboundMarker) || !Pointerp(fixups)) {
728 #ifdef GENCGC
729     /* Check for a possible errors. */
730     sniff_code_object(new_code,displacement);
731 #endif
732     return;
733   }
734
735   fixups_vector = (struct vector *)PTR(fixups);
736
737   /* Could be pointing to a forwarding pointer. */
738   if (Pointerp(fixups) && (dynamic_pointer_p(fixups))
739       && forwarding_pointer_p(*(lispobj *)fixups_vector)) {
740     /* If so then follow it. */
741     fixups_vector = (struct vector *)PTR(*(lispobj *)fixups_vector);
742   }
743
744   if (TypeOf(fixups_vector->header) == type_SimpleArrayUnsignedByte32) {
745     /* We got the fixups for the code block. Now work through the vector,
746      * and apply a fixup at each address. */
747     int length = fixnum_value(fixups_vector->length);
748     int i;
749     for (i=0; i<length; i++) {
750       unsigned offset = fixups_vector->data[i];
751       /* Now check the current value of offset. */
752       unsigned  old_value = *(unsigned *)((unsigned)code_start_addr + offset);
753
754       /* If it's within the old_code object then it must be an
755        * absolute fixup (relative ones are not saved) */
756       if ((old_value>=(unsigned)old_code)
757           && (old_value<((unsigned)old_code + nwords*4)))
758         /* So add the dispacement. */
759         *(unsigned *)((unsigned)code_start_addr + offset) = old_value
760           + displacement;
761       else
762         /* It is outside the old code object so it must be a relative
763          * fixup (absolute fixups are not saved). So subtract the
764          * displacement. */
765         *(unsigned *)((unsigned)code_start_addr + offset) = old_value
766           - displacement;
767     }
768   }
769
770   /* No longer need the fixups. */
771   new_code->constants[0] = 0;
772
773 #ifdef GENCGC
774   /* Check for possible errors. */
775   sniff_code_object(new_code,displacement);
776 #endif
777 }
778 #endif
779
780 static lispobj ptrans_code(lispobj thing)
781 {
782     struct code *code, *new;
783     int nwords;
784     lispobj func, result;
785
786     code = (struct code *)PTR(thing);
787     nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
788
789     new = (struct code *)read_only_free;
790     read_only_free += CEILING(nwords, 2);
791
792     bcopy(code, new, nwords * sizeof(lispobj));
793
794 #ifdef __i386__
795     apply_code_fixups_during_purify(code,new);
796 #endif
797
798     result = (lispobj)new | type_OtherPointer;
799
800     /* Stick in a forwarding pointer for the code object. */
801     *(lispobj *)code = result;
802
803     /* Put in forwarding pointers for all the functions. */
804     for (func = code->entry_points;
805          func != NIL;
806          func = ((struct function *)PTR(func))->next) {
807
808         gc_assert(LowtagOf(func) == type_FunctionPointer);
809
810         *(lispobj *)PTR(func) = result + (func - thing);
811     }
812
813     /* Arrange to scavenge the debug info later. */
814     pscav_later(&new->debug_info, 1);
815
816     if(new->trace_table_offset & 0x3)
817 #if 0
818       pscav(&new->trace_table_offset, 1, 0);
819 #else
820       new->trace_table_offset = NIL; /* limit lifetime */
821 #endif
822
823     /* Scavenge the constants. */
824     pscav(new->constants, HeaderValue(new->header)-5, 1);
825
826     /* Scavenge all the functions. */
827     pscav(&new->entry_points, 1, 1);
828     for (func = new->entry_points;
829          func != NIL;
830          func = ((struct function *)PTR(func))->next) {
831         gc_assert(LowtagOf(func) == type_FunctionPointer);
832         gc_assert(!dynamic_pointer_p(func));
833
834 #ifdef __i386__
835         /* Temporarly convert the self pointer to a real function
836            pointer. */
837         ((struct function *)PTR(func))->self -= RAW_ADDR_OFFSET;
838 #endif
839         pscav(&((struct function *)PTR(func))->self, 2, 1);
840 #ifdef __i386__
841         ((struct function *)PTR(func))->self += RAW_ADDR_OFFSET;
842 #endif
843         pscav_later(&((struct function *)PTR(func))->name, 3);
844     }
845
846     return result;
847 }
848
849 static lispobj ptrans_func(lispobj thing, lispobj header)
850 {
851     int nwords;
852     lispobj code, *new, *old, result;
853     struct function *function;
854
855     /* Thing can either be a function header, a closure function
856      * header, a closure, or a funcallable-instance. If it's a closure
857      * or a funcallable-instance, we do the same as ptrans_boxed.
858      * Otherwise we have to do something strange, 'cause it is buried
859      * inside a code object. */
860
861     if (TypeOf(header) == type_FunctionHeader ||
862         TypeOf(header) == type_ClosureFunctionHeader) {
863
864         /* We can only end up here if the code object has not been
865          * scavenged, because if it had been scavenged, forwarding pointers
866          * would have been left behind for all the entry points. */
867
868         function = (struct function *)PTR(thing);
869         code = (PTR(thing)-(HeaderValue(function->header)*sizeof(lispobj))) |
870             type_OtherPointer;
871
872         /* This will cause the function's header to be replaced with a 
873          * forwarding pointer. */
874         ptrans_code(code);
875
876         /* So we can just return that. */
877         return function->header;
878     }
879     else {
880         /* It's some kind of closure-like thing. */
881         nwords = 1 + HeaderValue(header);
882         old = (lispobj *)PTR(thing);
883
884         /* Allocate the new one. */
885         if (TypeOf(header) == type_FuncallableInstanceHeader) {
886             /* FINs *must* not go in read_only space. */
887             new = static_free;
888             static_free += CEILING(nwords, 2);
889         }
890         else {
891             /* Closures can always go in read-only space, 'cause they
892              * never change. */
893
894             new = read_only_free;
895             read_only_free += CEILING(nwords, 2);
896         }
897         /* Copy it. */
898         bcopy(old, new, nwords * sizeof(lispobj));
899
900         /* Deposit forwarding pointer. */
901         result = (lispobj)new | LowtagOf(thing);
902         *old = result;
903
904         /* Scavenge it. */
905         pscav(new, nwords, 0);
906
907         return result;
908     }
909 }
910
911 static lispobj ptrans_returnpc(lispobj thing, lispobj header)
912 {
913     lispobj code, new;
914
915     /* Find the corresponding code object. */
916     code = thing - HeaderValue(header)*sizeof(lispobj);
917
918     /* Make sure it's been transported. */
919     new = *(lispobj *)PTR(code);
920     if (!forwarding_pointer_p(new))
921         new = ptrans_code(code);
922
923     /* Maintain the offset: */
924     return new + (thing - code);
925 }
926
927 #define WORDS_PER_CONS CEILING(sizeof(struct cons) / sizeof(lispobj), 2)
928
929 static lispobj ptrans_list(lispobj thing, boolean constant)
930 {
931     struct cons *old, *new, *orig;
932     int length;
933
934     if (constant)
935         orig = (struct cons *)read_only_free;
936     else
937         orig = (struct cons *)static_free;
938     length = 0;
939
940     do {
941         /* Allocate a new cons cell. */
942         old = (struct cons *)PTR(thing);
943         if (constant) {
944             new = (struct cons *)read_only_free;
945             read_only_free += WORDS_PER_CONS;
946         }
947         else {
948             new = (struct cons *)static_free;
949             static_free += WORDS_PER_CONS;
950         }
951
952         /* Copy the cons cell and keep a pointer to the cdr. */
953         new->car = old->car;
954         thing = new->cdr = old->cdr;
955
956         /* Set up the forwarding pointer. */
957         *(lispobj *)old = ((lispobj)new) | type_ListPointer;
958
959         /* And count this cell. */
960         length++;
961     } while (LowtagOf(thing) == type_ListPointer &&
962              dynamic_pointer_p(thing) &&
963              !(forwarding_pointer_p(*(lispobj *)PTR(thing))));
964
965     /* Scavenge the list we just copied. */
966     pscav((lispobj *)orig, length * WORDS_PER_CONS, constant);
967
968     return ((lispobj)orig) | type_ListPointer;
969 }
970
971 static lispobj ptrans_otherptr(lispobj thing, lispobj header, boolean constant)
972 {
973     switch (TypeOf(header)) {
974       case type_Bignum:
975       case type_SingleFloat:
976       case type_DoubleFloat:
977 #ifdef type_LongFloat
978       case type_LongFloat:
979 #endif
980 #ifdef type_ComplexSingleFloat
981       case type_ComplexSingleFloat:
982 #endif
983 #ifdef type_ComplexDoubleFloat
984       case type_ComplexDoubleFloat:
985 #endif
986 #ifdef type_ComplexLongFloat
987       case type_ComplexLongFloat:
988 #endif
989       case type_Sap:
990         return ptrans_unboxed(thing, header);
991
992       case type_Ratio:
993       case type_Complex:
994       case type_SimpleArray:
995       case type_ComplexString:
996       case type_ComplexVector:
997       case type_ComplexArray:
998         return ptrans_boxed(thing, header, constant);
999         
1000       case type_ValueCellHeader:
1001       case type_WeakPointer:
1002         return ptrans_boxed(thing, header, 0);
1003
1004       case type_SymbolHeader:
1005         return ptrans_boxed(thing, header, 0);
1006
1007       case type_SimpleString:
1008         return ptrans_vector(thing, 8, 1, 0, constant);
1009
1010       case type_SimpleBitVector:
1011         return ptrans_vector(thing, 1, 0, 0, constant);
1012
1013       case type_SimpleVector:
1014         return ptrans_vector(thing, 32, 0, 1, constant);
1015
1016       case type_SimpleArrayUnsignedByte2:
1017         return ptrans_vector(thing, 2, 0, 0, constant);
1018
1019       case type_SimpleArrayUnsignedByte4:
1020         return ptrans_vector(thing, 4, 0, 0, constant);
1021
1022       case type_SimpleArrayUnsignedByte8:
1023 #ifdef type_SimpleArraySignedByte8
1024       case type_SimpleArraySignedByte8:
1025 #endif
1026         return ptrans_vector(thing, 8, 0, 0, constant);
1027
1028       case type_SimpleArrayUnsignedByte16:
1029 #ifdef type_SimpleArraySignedByte16
1030       case type_SimpleArraySignedByte16:
1031 #endif
1032         return ptrans_vector(thing, 16, 0, 0, constant);
1033
1034       case type_SimpleArrayUnsignedByte32:
1035 #ifdef type_SimpleArraySignedByte30
1036       case type_SimpleArraySignedByte30:
1037 #endif
1038 #ifdef type_SimpleArraySignedByte32
1039       case type_SimpleArraySignedByte32:
1040 #endif
1041         return ptrans_vector(thing, 32, 0, 0, constant);
1042
1043       case type_SimpleArraySingleFloat:
1044         return ptrans_vector(thing, 32, 0, 0, constant);
1045
1046       case type_SimpleArrayDoubleFloat:
1047         return ptrans_vector(thing, 64, 0, 0, constant);
1048
1049 #ifdef type_SimpleArrayLongFloat
1050       case type_SimpleArrayLongFloat:
1051 #ifdef __i386__
1052         return ptrans_vector(thing, 96, 0, 0, constant);
1053 #endif
1054 #ifdef sparc
1055         return ptrans_vector(thing, 128, 0, 0, constant);
1056 #endif
1057 #endif
1058
1059 #ifdef type_SimpleArrayComplexSingleFloat
1060       case type_SimpleArrayComplexSingleFloat:
1061         return ptrans_vector(thing, 64, 0, 0, constant);
1062 #endif
1063
1064 #ifdef type_SimpleArrayComplexDoubleFloat
1065       case type_SimpleArrayComplexDoubleFloat:
1066         return ptrans_vector(thing, 128, 0, 0, constant);
1067 #endif
1068
1069 #ifdef type_SimpleArrayComplexLongFloat
1070       case type_SimpleArrayComplexLongFloat:
1071 #ifdef __i386__
1072         return ptrans_vector(thing, 192, 0, 0, constant);
1073 #endif
1074 #ifdef sparc
1075         return ptrans_vector(thing, 256, 0, 0, constant);
1076 #endif
1077 #endif
1078
1079       case type_CodeHeader:
1080         return ptrans_code(thing);
1081
1082       case type_ReturnPcHeader:
1083         return ptrans_returnpc(thing, header);
1084
1085       case type_Fdefn:
1086         return ptrans_fdefn(thing, header);
1087
1088       default:
1089         /* Should only come across other pointers to the above stuff. */
1090         gc_abort();
1091         return NIL;
1092     }
1093 }
1094
1095 static int pscav_fdefn(struct fdefn *fdefn)
1096 {
1097     boolean fix_func;
1098
1099     fix_func = ((char *)(fdefn->function+RAW_ADDR_OFFSET) == fdefn->raw_addr);
1100     pscav(&fdefn->name, 1, 1);
1101     pscav(&fdefn->function, 1, 0);
1102     if (fix_func)
1103         fdefn->raw_addr = (char *)(fdefn->function + RAW_ADDR_OFFSET);
1104     return sizeof(struct fdefn) / sizeof(lispobj);
1105 }
1106
1107 #ifdef __i386__
1108 /* now putting code objects in static space */
1109 static int
1110 pscav_code(struct code*code)
1111 {
1112     int nwords;
1113     lispobj func;
1114     nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
1115
1116     /* pw--The trace_table_offset slot can contain a list pointer. This
1117      * occurs when the code object is a top level form that initializes
1118      * a byte-compiled function. The fact that PURIFY was ignoring this
1119      * slot may be a bug unrelated to the x86 port, except that TLF's
1120      * normally become unreachable after the loader calls them and
1121      * won't be seen by PURIFY at all!! */
1122     if(code->trace_table_offset & 0x3)
1123 #if 0
1124       pscav(&code->trace_table_offset, 1, 0);
1125 #else
1126       code->trace_table_offset = NIL; /* limit lifetime */
1127 #endif
1128
1129     /* Arrange to scavenge the debug info later. */
1130     pscav_later(&code->debug_info, 1);
1131
1132     /* Scavenge the constants. */
1133     pscav(code->constants, HeaderValue(code->header)-5, 1);
1134
1135     /* Scavenge all the functions. */
1136     pscav(&code->entry_points, 1, 1);
1137     for (func = code->entry_points;
1138          func != NIL;
1139          func = ((struct function *)PTR(func))->next) {
1140         gc_assert(LowtagOf(func) == type_FunctionPointer);
1141         gc_assert(!dynamic_pointer_p(func));
1142
1143 #ifdef __i386__
1144         /* Temporarly convert the self pointer to a real function
1145          * pointer. */
1146         ((struct function *)PTR(func))->self -= RAW_ADDR_OFFSET;
1147 #endif
1148         pscav(&((struct function *)PTR(func))->self, 2, 1);
1149 #ifdef __i386__
1150         ((struct function *)PTR(func))->self += RAW_ADDR_OFFSET;
1151 #endif
1152         pscav_later(&((struct function *)PTR(func))->name, 3);
1153     }
1154
1155     return CEILING(nwords,2);
1156 }
1157 #endif
1158
1159 static lispobj *pscav(lispobj *addr, int nwords, boolean constant)
1160 {
1161     lispobj thing, *thingp, header;
1162     int count = 0; /* (0 = dummy init value to stop GCC warning) */
1163     struct vector *vector;
1164
1165     while (nwords > 0) {
1166         thing = *addr;
1167         if (Pointerp(thing)) {
1168             /* It's a pointer. Is it something we might have to move? */
1169             if (dynamic_pointer_p(thing)) {
1170                 /* Maybe. Have we already moved it? */
1171                 thingp = (lispobj *)PTR(thing);
1172                 header = *thingp;
1173                 if (Pointerp(header) && forwarding_pointer_p(header))
1174                     /* Yep, so just copy the forwarding pointer. */
1175                     thing = header;
1176                 else {
1177                     /* Nope, copy the object. */
1178                     switch (LowtagOf(thing)) {
1179                       case type_FunctionPointer:
1180                         thing = ptrans_func(thing, header);
1181                         break;
1182
1183                       case type_ListPointer:
1184                         thing = ptrans_list(thing, constant);
1185                         break;
1186
1187                       case type_InstancePointer:
1188                         thing = ptrans_instance(thing, header, constant);
1189                         break;
1190
1191                       case type_OtherPointer:
1192                         thing = ptrans_otherptr(thing, header, constant);
1193                         break;
1194
1195                       default:
1196                         /* It was a pointer, but not one of them? */
1197                         gc_abort();
1198                     }
1199                 }
1200                 *addr = thing;
1201             }
1202             count = 1;
1203         }
1204         else if (thing & 3) {
1205             /* It's an other immediate. Maybe the header for an unboxed */
1206             /* object. */
1207             switch (TypeOf(thing)) {
1208               case type_Bignum:
1209               case type_SingleFloat:
1210               case type_DoubleFloat:
1211 #ifdef type_LongFloat
1212               case type_LongFloat:
1213 #endif
1214               case type_Sap:
1215                 /* It's an unboxed simple object. */
1216                 count = HeaderValue(thing)+1;
1217                 break;
1218
1219               case type_SimpleVector:
1220                 if (HeaderValue(thing) == subtype_VectorValidHashing)
1221                     *addr = (subtype_VectorMustRehash<<type_Bits) |
1222                         type_SimpleVector;
1223                 count = 1;
1224                 break;
1225
1226               case type_SimpleString:
1227                 vector = (struct vector *)addr;
1228                 count = CEILING(NWORDS(fixnum_value(vector->length)+1,4)+2,2);
1229                 break;
1230
1231               case type_SimpleBitVector:
1232                 vector = (struct vector *)addr;
1233                 count = CEILING(NWORDS(fixnum_value(vector->length),32)+2,2);
1234                 break;
1235
1236               case type_SimpleArrayUnsignedByte2:
1237                 vector = (struct vector *)addr;
1238                 count = CEILING(NWORDS(fixnum_value(vector->length),16)+2,2);
1239                 break;
1240
1241               case type_SimpleArrayUnsignedByte4:
1242                 vector = (struct vector *)addr;
1243                 count = CEILING(NWORDS(fixnum_value(vector->length),8)+2,2);
1244                 break;
1245
1246               case type_SimpleArrayUnsignedByte8:
1247 #ifdef type_SimpleArraySignedByte8
1248               case type_SimpleArraySignedByte8:
1249 #endif
1250                 vector = (struct vector *)addr;
1251                 count = CEILING(NWORDS(fixnum_value(vector->length),4)+2,2);
1252                 break;
1253
1254               case type_SimpleArrayUnsignedByte16:
1255 #ifdef type_SimpleArraySignedByte16
1256               case type_SimpleArraySignedByte16:
1257 #endif
1258                 vector = (struct vector *)addr;
1259                 count = CEILING(NWORDS(fixnum_value(vector->length),2)+2,2);
1260                 break;
1261
1262               case type_SimpleArrayUnsignedByte32:
1263 #ifdef type_SimpleArraySignedByte30
1264               case type_SimpleArraySignedByte30:
1265 #endif
1266 #ifdef type_SimpleArraySignedByte32
1267               case type_SimpleArraySignedByte32:
1268 #endif
1269                 vector = (struct vector *)addr;
1270                 count = CEILING(fixnum_value(vector->length)+2,2);
1271                 break;
1272
1273               case type_SimpleArraySingleFloat:
1274                 vector = (struct vector *)addr;
1275                 count = CEILING(fixnum_value(vector->length)+2,2);
1276                 break;
1277
1278               case type_SimpleArrayDoubleFloat:
1279 #ifdef type_SimpleArrayComplexSingleFloat
1280               case type_SimpleArrayComplexSingleFloat:
1281 #endif
1282                 vector = (struct vector *)addr;
1283                 count = fixnum_value(vector->length)*2+2;
1284                 break;
1285
1286 #ifdef type_SimpleArrayLongFloat
1287               case type_SimpleArrayLongFloat:
1288                 vector = (struct vector *)addr;
1289 #ifdef __i386__
1290                 count = fixnum_value(vector->length)*3+2;
1291 #endif
1292 #ifdef sparc
1293                 count = fixnum_value(vector->length)*4+2;
1294 #endif
1295                 break;
1296 #endif
1297
1298 #ifdef type_SimpleArrayComplexDoubleFloat
1299               case type_SimpleArrayComplexDoubleFloat:
1300                 vector = (struct vector *)addr;
1301                 count = fixnum_value(vector->length)*4+2;
1302                 break;
1303 #endif
1304
1305 #ifdef type_SimpleArrayComplexLongFloat
1306               case type_SimpleArrayComplexLongFloat:
1307                 vector = (struct vector *)addr;
1308 #ifdef __i386__
1309                 count = fixnum_value(vector->length)*6+2;
1310 #endif
1311 #ifdef sparc
1312                 count = fixnum_value(vector->length)*8+2;
1313 #endif
1314                 break;
1315 #endif
1316
1317               case type_CodeHeader:
1318 #ifndef __i386__
1319                 gc_abort(); /* no code headers in static space */
1320 #else
1321                 count = pscav_code((struct code*)addr);
1322 #endif
1323                 break;
1324
1325               case type_FunctionHeader:
1326               case type_ClosureFunctionHeader:
1327               case type_ReturnPcHeader:
1328                 /* We should never hit any of these, 'cause they occur
1329                  * buried in the middle of code objects. */
1330                 gc_abort();
1331                 break;
1332
1333 #ifdef __i386__
1334               case type_ClosureHeader:
1335               case type_FuncallableInstanceHeader:
1336               case type_ByteCodeFunction:
1337               case type_ByteCodeClosure:
1338                 /* The function self pointer needs special care on the
1339                  * x86 because it is the real entry point. */
1340                 {
1341                   lispobj fun = ((struct closure *)addr)->function
1342                     - RAW_ADDR_OFFSET;
1343                   pscav(&fun, 1, constant);
1344                   ((struct closure *)addr)->function = fun + RAW_ADDR_OFFSET;
1345                 }
1346                 count = 2;
1347                 break;
1348 #endif
1349
1350               case type_WeakPointer:
1351                 /* Weak pointers get preserved during purify, 'cause I
1352                  * don't feel like figuring out how to break them. */
1353                 pscav(addr+1, 2, constant);
1354                 count = 4;
1355                 break;
1356
1357               case type_Fdefn:
1358                 /* We have to handle fdefn objects specially, so we
1359                  * can fix up the raw function address. */
1360                 count = pscav_fdefn((struct fdefn *)addr);
1361                 break;
1362
1363               default:
1364                 count = 1;
1365                 break;
1366             }
1367         }
1368         else {
1369             /* It's a fixnum. */
1370             count = 1;
1371         }
1372
1373         addr += count;
1374         nwords -= count;
1375     }
1376
1377     return addr;
1378 }
1379
1380 int purify(lispobj static_roots, lispobj read_only_roots)
1381 {
1382     lispobj *clean;
1383     int count, i;
1384     struct later *laters, *next;
1385
1386 #ifdef PRINTNOISE
1387     printf("[doing purification:");
1388     fflush(stdout);
1389 #endif
1390
1391     if (fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX)) != 0) {
1392         /* FIXME: 1. What does this mean? 2. It shouldn't be reporting
1393          * its error simply by a. printing a string b. to stdout instead
1394          * of stderr. */
1395         printf(" Ack! Can't purify interrupt contexts. ");
1396         fflush(stdout);
1397         return 0;
1398     }
1399
1400 #if defined(ibmrt) || defined(__i386__)
1401     dynamic_space_free_pointer =
1402       (lispobj*)SymbolValue(ALLOCATION_POINTER);
1403 #endif
1404
1405     read_only_end = read_only_free =
1406         (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER);
1407     static_end = static_free =
1408         (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER);
1409
1410 #ifdef PRINTNOISE
1411     printf(" roots");
1412     fflush(stdout);
1413 #endif
1414
1415 #ifdef GENCGC
1416     gc_assert((lispobj *)CONTROL_STACK_END > ((&read_only_roots)+1));
1417     setup_i386_stack_scav(((&static_roots)-2), (lispobj *)CONTROL_STACK_END);
1418 #endif
1419
1420     pscav(&static_roots, 1, 0);
1421     pscav(&read_only_roots, 1, 1);
1422
1423 #ifdef PRINTNOISE
1424     printf(" handlers");
1425     fflush(stdout);
1426 #endif
1427     pscav((lispobj *) interrupt_handlers,
1428           sizeof(interrupt_handlers) / sizeof(lispobj),
1429           0);
1430
1431 #ifdef PRINTNOISE
1432     printf(" stack");
1433     fflush(stdout);
1434 #endif
1435 #ifndef __i386__
1436     pscav((lispobj *)CONTROL_STACK_START,
1437           current_control_stack_pointer - (lispobj *)CONTROL_STACK_START,
1438           0);
1439 #else
1440 #ifdef GENCGC
1441     pscav_i386_stack();
1442 #endif
1443 #ifdef WANT_CGC
1444     gc_assert((lispobj *)control_stack_end > ((&read_only_roots)+1));
1445     carefully_pscav_stack(((&read_only_roots)+1),
1446                           (lispobj *)CONTROL_STACK_END);
1447 #endif
1448 #endif
1449
1450 #ifdef PRINTNOISE
1451     printf(" bindings");
1452     fflush(stdout);
1453 #endif
1454 #if !defined(ibmrt) && !defined(__i386__)
1455     pscav( (lispobj *)BINDING_STACK_START,
1456           (lispobj *)current_binding_stack_pointer - (lispobj *)BINDING_STACK_START,
1457           0);
1458 #else
1459     pscav( (lispobj *)BINDING_STACK_START,
1460           (lispobj *)SymbolValue(BINDING_STACK_POINTER) -
1461           (lispobj *)BINDING_STACK_START,
1462           0);
1463 #endif
1464
1465 #ifdef SCAVENGE_READ_ONLY_SPACE
1466     if (SymbolValue(SCAVENGE_READ_ONLY_SPACE) != type_UnboundMarker
1467         && SymbolValue(SCAVENGE_READ_ONLY_SPACE) != NIL) {
1468       unsigned  read_only_space_size =
1469           (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) -
1470           (lispobj *)READ_ONLY_SPACE_START;
1471       fprintf(stderr,
1472               "scavenging read only space: %d bytes\n",
1473               read_only_space_size * sizeof(lispobj));
1474       pscav( (lispobj *)READ_ONLY_SPACE_START, read_only_space_size, 0);
1475     }
1476 #endif
1477
1478 #ifdef PRINTNOISE
1479     printf(" static");
1480     fflush(stdout);
1481 #endif
1482     clean = (lispobj *)STATIC_SPACE_START;
1483     do {
1484         while (clean != static_free)
1485             clean = pscav(clean, static_free - clean, 0);
1486         laters = later_blocks;
1487         count = later_count;
1488         later_blocks = NULL;
1489         later_count = 0;
1490         while (laters != NULL) {
1491             for (i = 0; i < count; i++) {
1492                 if (laters->u[i].count == 0) {
1493                     ;
1494                 } else if (laters->u[i].count <= LATERMAXCOUNT) {
1495                     pscav(laters->u[i+1].ptr, laters->u[i].count, 1);
1496                     i++;
1497                 } else {
1498                     pscav(laters->u[i].ptr, 1, 1);
1499                 }
1500             }
1501             next = laters->next;
1502             free(laters);
1503             laters = next;
1504             count = LATERBLOCKSIZE;
1505         }
1506     } while (clean != static_free || later_blocks != NULL);
1507
1508 #ifdef PRINTNOISE
1509     printf(" cleanup");
1510     fflush(stdout);
1511 #endif
1512
1513 #if defined(WANT_CGC) && defined(X86_CGC_ACTIVE_P)
1514     if(SymbolValue(X86_CGC_ACTIVE_P) != T) {
1515         os_zero((os_vm_address_t) DYNAMIC_SPACE_START,
1516                 (os_vm_size_t) DYNAMIC_SPACE_SIZE);
1517     }
1518 #else
1519     os_zero((os_vm_address_t) current_dynamic_space,
1520             (os_vm_size_t) DYNAMIC_SPACE_SIZE);
1521 #endif
1522
1523     /* Zero the stack. Note that the stack is also zeroed by SUB-GC
1524      * calling SCRUB-CONTROL-STACK - this zeros the stack on the x86. */
1525 #ifndef __i386__
1526     os_zero((os_vm_address_t) current_control_stack_pointer,
1527             (os_vm_size_t) (CONTROL_STACK_SIZE -
1528                             ((current_control_stack_pointer -
1529                               (lispobj *)CONTROL_STACK_START) *
1530                              sizeof(lispobj))));
1531 #endif
1532
1533 #if defined(WANT_CGC) && defined(STATIC_BLUE_BAG)
1534     {
1535       lispobj bag = SymbolValue(STATIC_BLUE_BAG);
1536       struct cons*cons = (struct cons*)static_free;
1537       struct cons*pair = cons + 1;
1538       static_free += 2*WORDS_PER_CONS;
1539       if(bag == type_UnboundMarker)
1540         bag = NIL;
1541       cons->cdr = bag;
1542       cons->car = (lispobj)pair | type_ListPointer;
1543       pair->car = (lispobj)static_end;
1544       pair->cdr = (lispobj)static_free;
1545       bag = (lispobj)cons | type_ListPointer;
1546       SetSymbolValue(STATIC_BLUE_BAG, bag);
1547     }
1548 #endif
1549
1550     /* It helps to update the heap free pointers so that free_heap can
1551      * verify after it's done. */
1552     SetSymbolValue(READ_ONLY_SPACE_FREE_POINTER, (lispobj)read_only_free);
1553     SetSymbolValue(STATIC_SPACE_FREE_POINTER, (lispobj)static_free);
1554
1555 #if !defined(ibmrt) && !defined(__i386__)
1556     dynamic_space_free_pointer = current_dynamic_space;
1557 #else
1558 #if defined(WANT_CGC) && defined(X86_CGC_ACTIVE_P)
1559     /* X86 using CGC */
1560     if(SymbolValue(X86_CGC_ACTIVE_P) != T)
1561         SetSymbolValue(ALLOCATION_POINTER, (lispobj)DYNAMIC_SPACE_START);
1562     else
1563         cgc_free_heap();
1564 #else
1565 #if defined GENCGC
1566     gc_free_heap();
1567 #else
1568     /* ibmrt using GC */
1569     SetSymbolValue(ALLOCATION_POINTER, (lispobj)DYNAMIC_SPACE_START);
1570 #endif
1571 #endif
1572 #endif
1573
1574 #ifdef PRINTNOISE
1575     printf(" done]\n");
1576     fflush(stdout);
1577 #endif
1578
1579     return 0;
1580 }