8a9591f99d268bc61ab4f09dc672a31562ce45b1
[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 a 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
456              * return addresses. This will also pick up pointers to
457              * functions in code objects. */
458             if (TypeOf(*start_addr) == type_CodeHeader) {
459                 gc_assert(num_valid_stack_ra_locations <
460                           MAX_STACK_RETURN_ADDRESSES);
461                 valid_stack_ra_locations[num_valid_stack_ra_locations] = sp;
462                 valid_stack_ra_code_objects[num_valid_stack_ra_locations++] =
463                     (lispobj *)((int)start_addr + type_OtherPointer);
464             } else {
465                 if (valid_dynamic_space_pointer((void *)thing, start_addr)) {
466                     gc_assert(num_valid_stack_locations < MAX_STACK_POINTERS);
467                     valid_stack_locations[num_valid_stack_locations++] = sp;
468                 }
469             }
470         }
471     }
472     if (pointer_filter_verbose) {
473         fprintf(stderr, "number of valid stack pointers = %d\n",
474                 num_valid_stack_locations);
475         fprintf(stderr, "number of stack return addresses = %d\n",
476                 num_valid_stack_ra_locations);
477     }
478 }
479
480 static void
481 pscav_i386_stack(void)
482 {
483     int i;
484
485     for (i = 0; i < num_valid_stack_locations; i++)
486         pscav(valid_stack_locations[i], 1, 0);
487
488     for (i = 0; i < num_valid_stack_ra_locations; i++) {
489         lispobj code_obj = (lispobj)valid_stack_ra_code_objects[i];
490         pscav(&code_obj, 1, 0);
491         if (pointer_filter_verbose) {
492             fprintf(stderr,"*C moved RA %x to %x; for code object %x to %x\n",
493                     *valid_stack_ra_locations[i],
494                     (int)(*valid_stack_ra_locations[i])
495                     - ((int)valid_stack_ra_code_objects[i] - (int)code_obj),
496                     (unsigned int) valid_stack_ra_code_objects[i], code_obj);
497         }
498         *valid_stack_ra_locations[i] =
499             ((int)(*valid_stack_ra_locations[i])
500              - ((int)valid_stack_ra_code_objects[i] - (int)code_obj));
501     }
502 }
503 #endif
504 #endif
505
506 \f
507 static void
508 pscav_later(lispobj *where, int count)
509 {
510     struct later *new;
511
512     if (count > LATERMAXCOUNT) {
513         while (count > LATERMAXCOUNT) {
514             pscav_later(where, LATERMAXCOUNT);
515             count -= LATERMAXCOUNT;
516             where += LATERMAXCOUNT;
517         }
518     }
519     else {
520         if (later_blocks == NULL || later_count == LATERBLOCKSIZE ||
521             (later_count == LATERBLOCKSIZE-1 && count > 1)) {
522             new  = (struct later *)malloc(sizeof(struct later));
523             new->next = later_blocks;
524             if (later_blocks && later_count < LATERBLOCKSIZE)
525                 later_blocks->u[later_count].ptr = NULL;
526             later_blocks = new;
527             later_count = 0;
528         }
529
530         if (count != 1)
531             later_blocks->u[later_count++].count = count;
532         later_blocks->u[later_count++].ptr = where;
533     }
534 }
535
536 static lispobj
537 ptrans_boxed(lispobj thing, lispobj header, boolean constant)
538 {
539     int nwords;
540     lispobj result, *new, *old;
541
542     nwords = 1 + HeaderValue(header);
543
544     /* Allocate it */
545     old = (lispobj *)PTR(thing);
546     if (constant) {
547         new = read_only_free;
548         read_only_free += CEILING(nwords, 2);
549     }
550     else {
551         new = static_free;
552         static_free += CEILING(nwords, 2);
553     }
554
555     /* Copy it. */
556     bcopy(old, new, nwords * sizeof(lispobj));
557
558     /* Deposit forwarding pointer. */
559     result = (lispobj)new | LowtagOf(thing);
560     *old = result;
561
562     /* Scavenge it. */
563     pscav(new, nwords, constant);
564
565     return result;
566 }
567
568 /* We need to look at the layout to see whether it is a pure structure
569  * class, and only then can we transport as constant. If it is pure,
570  * we can ALWAYS transport as a constant. */
571 static lispobj
572 ptrans_instance(lispobj thing, lispobj header, boolean constant)
573 {
574     lispobj layout = ((struct instance *)PTR(thing))->slots[0];
575     lispobj pure = ((struct instance *)PTR(layout))->slots[15];
576
577     switch (pure) {
578     case T:
579         return (ptrans_boxed(thing, header, 1));
580     case NIL:
581         return (ptrans_boxed(thing, header, 0));
582     case 0:
583         {
584             /* Substructure: special case for the COMPACT-INFO-ENVs, where
585              * the instance may have a point to the dynamic space placed
586              * into it (e.g. the cache-name slot), but the lists and arrays
587              * at the time of a purify can be moved to the RO space. */
588             int nwords;
589             lispobj result, *new, *old;
590
591             nwords = 1 + HeaderValue(header);
592
593             /* Allocate it */
594             old = (lispobj *)PTR(thing);
595             new = static_free;
596             static_free += CEILING(nwords, 2);
597
598             /* Copy it. */
599             bcopy(old, new, nwords * sizeof(lispobj));
600
601             /* Deposit forwarding pointer. */
602             result = (lispobj)new | LowtagOf(thing);
603             *old = result;
604
605             /* Scavenge it. */
606             pscav(new, nwords, 1);
607
608             return result;
609         }
610     default:
611         gc_abort();
612         return NIL; /* dummy value: return something ... */
613     }
614 }
615
616 static lispobj
617 ptrans_fdefn(lispobj thing, lispobj header)
618 {
619     int nwords;
620     lispobj result, *new, *old, oldfn;
621     struct fdefn *fdefn;
622
623     nwords = 1 + HeaderValue(header);
624
625     /* Allocate it */
626     old = (lispobj *)PTR(thing);
627     new = static_free;
628     static_free += CEILING(nwords, 2);
629
630     /* Copy it. */
631     bcopy(old, new, nwords * sizeof(lispobj));
632
633     /* Deposit forwarding pointer. */
634     result = (lispobj)new | LowtagOf(thing);
635     *old = result;
636
637     /* Scavenge the function. */
638     fdefn = (struct fdefn *)new;
639     oldfn = fdefn->function;
640     pscav(&fdefn->function, 1, 0);
641     if ((char *)oldfn + RAW_ADDR_OFFSET == fdefn->raw_addr)
642         fdefn->raw_addr = (char *)fdefn->function + RAW_ADDR_OFFSET;
643
644     return result;
645 }
646
647 static lispobj
648 ptrans_unboxed(lispobj thing, lispobj header)
649 {
650     int nwords;
651     lispobj result, *new, *old;
652
653     nwords = 1 + HeaderValue(header);
654
655     /* Allocate it */
656     old = (lispobj *)PTR(thing);
657     new = read_only_free;
658     read_only_free += CEILING(nwords, 2);
659
660     /* Copy it. */
661     bcopy(old, new, nwords * sizeof(lispobj));
662
663     /* Deposit forwarding pointer. */
664     result = (lispobj)new | LowtagOf(thing);
665     *old = result;
666
667     return result;
668 }
669
670 static lispobj
671 ptrans_vector(lispobj thing, int bits, int extra,
672               boolean boxed, boolean constant)
673 {
674     struct vector *vector;
675     int nwords;
676     lispobj result, *new;
677
678     vector = (struct vector *)PTR(thing);
679     nwords = 2 + (CEILING((fixnum_value(vector->length)+extra)*bits,32)>>5);
680
681     if (boxed && !constant) {
682         new = static_free;
683         static_free += CEILING(nwords, 2);
684     }
685     else {
686         new = read_only_free;
687         read_only_free += CEILING(nwords, 2);
688     }
689
690     bcopy(vector, new, nwords * sizeof(lispobj));
691
692     result = (lispobj)new | LowtagOf(thing);
693     vector->header = result;
694
695     if (boxed)
696         pscav(new, nwords, constant);
697
698     return result;
699 }
700
701 #ifdef __i386__
702 static void
703 apply_code_fixups_during_purify(struct code *old_code, struct code *new_code)
704 {
705   int nheader_words, ncode_words, nwords;
706   void  *constants_start_addr, *constants_end_addr;
707   void  *code_start_addr, *code_end_addr;
708   lispobj fixups = NIL;
709   unsigned  displacement = (unsigned)new_code - (unsigned)old_code;
710   struct vector *fixups_vector;
711
712   /* Byte compiled code has no fixups. The trace table offset will be
713    * a fixnum if it's x86 compiled code - check. */
714   if (new_code->trace_table_offset & 0x3)
715     return;
716
717   /* Else it's x86 machine code. */
718   ncode_words = fixnum_value(new_code->code_size);
719   nheader_words = HeaderValue(*(lispobj *)new_code);
720   nwords = ncode_words + nheader_words;
721
722   constants_start_addr = (void *)new_code + 5*4;
723   constants_end_addr = (void *)new_code + nheader_words*4;
724   code_start_addr = (void *)new_code + nheader_words*4;
725   code_end_addr = (void *)new_code + nwords*4;
726
727   /* The first constant should be a pointer to the fixups for this
728    * code objects. Check. */
729   fixups = new_code->constants[0];
730
731   /* It will be 0 or the unbound-marker if there are no fixups, and
732    * will be an other-pointer to a vector if it is valid. */
733   if ((fixups==0) || (fixups==type_UnboundMarker) || !Pointerp(fixups)) {
734 #ifdef GENCGC
735     /* Check for a possible errors. */
736     sniff_code_object(new_code,displacement);
737 #endif
738     return;
739   }
740
741   fixups_vector = (struct vector *)PTR(fixups);
742
743   /* Could be pointing to a forwarding pointer. */
744   if (Pointerp(fixups) && (dynamic_pointer_p(fixups))
745       && forwarding_pointer_p(*(lispobj *)fixups_vector)) {
746     /* If so then follow it. */
747     fixups_vector = (struct vector *)PTR(*(lispobj *)fixups_vector);
748   }
749
750   if (TypeOf(fixups_vector->header) == type_SimpleArrayUnsignedByte32) {
751     /* We got the fixups for the code block. Now work through the vector,
752      * and apply a fixup at each address. */
753     int length = fixnum_value(fixups_vector->length);
754     int i;
755     for (i=0; i<length; i++) {
756       unsigned offset = fixups_vector->data[i];
757       /* Now check the current value of offset. */
758       unsigned  old_value = *(unsigned *)((unsigned)code_start_addr + offset);
759
760       /* If it's within the old_code object then it must be an
761        * absolute fixup (relative ones are not saved) */
762       if ((old_value>=(unsigned)old_code)
763           && (old_value<((unsigned)old_code + nwords*4)))
764         /* So add the dispacement. */
765         *(unsigned *)((unsigned)code_start_addr + offset) = old_value
766           + displacement;
767       else
768         /* It is outside the old code object so it must be a relative
769          * fixup (absolute fixups are not saved). So subtract the
770          * displacement. */
771         *(unsigned *)((unsigned)code_start_addr + offset) = old_value
772           - displacement;
773     }
774   }
775
776   /* No longer need the fixups. */
777   new_code->constants[0] = 0;
778
779 #ifdef GENCGC
780   /* Check for possible errors. */
781   sniff_code_object(new_code,displacement);
782 #endif
783 }
784 #endif
785
786 static lispobj
787 ptrans_code(lispobj thing)
788 {
789     struct code *code, *new;
790     int nwords;
791     lispobj func, result;
792
793     code = (struct code *)PTR(thing);
794     nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
795
796     new = (struct code *)read_only_free;
797     read_only_free += CEILING(nwords, 2);
798
799     bcopy(code, new, nwords * sizeof(lispobj));
800
801 #ifdef __i386__
802     apply_code_fixups_during_purify(code,new);
803 #endif
804
805     result = (lispobj)new | type_OtherPointer;
806
807     /* Stick in a forwarding pointer for the code object. */
808     *(lispobj *)code = result;
809
810     /* Put in forwarding pointers for all the functions. */
811     for (func = code->entry_points;
812          func != NIL;
813          func = ((struct function *)PTR(func))->next) {
814
815         gc_assert(LowtagOf(func) == type_FunctionPointer);
816
817         *(lispobj *)PTR(func) = result + (func - thing);
818     }
819
820     /* Arrange to scavenge the debug info later. */
821     pscav_later(&new->debug_info, 1);
822
823     if(new->trace_table_offset & 0x3)
824 #if 0
825       pscav(&new->trace_table_offset, 1, 0);
826 #else
827       new->trace_table_offset = NIL; /* limit lifetime */
828 #endif
829
830     /* Scavenge the constants. */
831     pscav(new->constants, HeaderValue(new->header)-5, 1);
832
833     /* Scavenge all the functions. */
834     pscav(&new->entry_points, 1, 1);
835     for (func = new->entry_points;
836          func != NIL;
837          func = ((struct function *)PTR(func))->next) {
838         gc_assert(LowtagOf(func) == type_FunctionPointer);
839         gc_assert(!dynamic_pointer_p(func));
840
841 #ifdef __i386__
842         /* Temporarly convert the self pointer to a real function
843            pointer. */
844         ((struct function *)PTR(func))->self -= RAW_ADDR_OFFSET;
845 #endif
846         pscav(&((struct function *)PTR(func))->self, 2, 1);
847 #ifdef __i386__
848         ((struct function *)PTR(func))->self += RAW_ADDR_OFFSET;
849 #endif
850         pscav_later(&((struct function *)PTR(func))->name, 3);
851     }
852
853     return result;
854 }
855
856 static lispobj
857 ptrans_func(lispobj thing, lispobj header)
858 {
859     int nwords;
860     lispobj code, *new, *old, result;
861     struct function *function;
862
863     /* Thing can either be a function header, a closure function
864      * header, a closure, or a funcallable-instance. If it's a closure
865      * or a funcallable-instance, we do the same as ptrans_boxed.
866      * Otherwise we have to do something strange, 'cause it is buried
867      * inside a code object. */
868
869     if (TypeOf(header) == type_FunctionHeader ||
870         TypeOf(header) == type_ClosureFunctionHeader) {
871
872         /* We can only end up here if the code object has not been
873          * scavenged, because if it had been scavenged, forwarding pointers
874          * would have been left behind for all the entry points. */
875
876         function = (struct function *)PTR(thing);
877         code = (PTR(thing)-(HeaderValue(function->header)*sizeof(lispobj))) |
878             type_OtherPointer;
879
880         /* This will cause the function's header to be replaced with a 
881          * forwarding pointer. */
882         ptrans_code(code);
883
884         /* So we can just return that. */
885         return function->header;
886     }
887     else {
888         /* It's some kind of closure-like thing. */
889         nwords = 1 + HeaderValue(header);
890         old = (lispobj *)PTR(thing);
891
892         /* Allocate the new one. */
893         if (TypeOf(header) == type_FuncallableInstanceHeader) {
894             /* FINs *must* not go in read_only space. */
895             new = static_free;
896             static_free += CEILING(nwords, 2);
897         }
898         else {
899             /* Closures can always go in read-only space, 'cause they
900              * never change. */
901
902             new = read_only_free;
903             read_only_free += CEILING(nwords, 2);
904         }
905         /* Copy it. */
906         bcopy(old, new, nwords * sizeof(lispobj));
907
908         /* Deposit forwarding pointer. */
909         result = (lispobj)new | LowtagOf(thing);
910         *old = result;
911
912         /* Scavenge it. */
913         pscav(new, nwords, 0);
914
915         return result;
916     }
917 }
918
919 static lispobj
920 ptrans_returnpc(lispobj thing, lispobj header)
921 {
922     lispobj code, new;
923
924     /* Find the corresponding code object. */
925     code = thing - HeaderValue(header)*sizeof(lispobj);
926
927     /* Make sure it's been transported. */
928     new = *(lispobj *)PTR(code);
929     if (!forwarding_pointer_p(new))
930         new = ptrans_code(code);
931
932     /* Maintain the offset: */
933     return new + (thing - code);
934 }
935
936 #define WORDS_PER_CONS CEILING(sizeof(struct cons) / sizeof(lispobj), 2)
937
938 static lispobj
939 ptrans_list(lispobj thing, boolean constant)
940 {
941     struct cons *old, *new, *orig;
942     int length;
943
944     if (constant)
945         orig = (struct cons *)read_only_free;
946     else
947         orig = (struct cons *)static_free;
948     length = 0;
949
950     do {
951         /* Allocate a new cons cell. */
952         old = (struct cons *)PTR(thing);
953         if (constant) {
954             new = (struct cons *)read_only_free;
955             read_only_free += WORDS_PER_CONS;
956         }
957         else {
958             new = (struct cons *)static_free;
959             static_free += WORDS_PER_CONS;
960         }
961
962         /* Copy the cons cell and keep a pointer to the cdr. */
963         new->car = old->car;
964         thing = new->cdr = old->cdr;
965
966         /* Set up the forwarding pointer. */
967         *(lispobj *)old = ((lispobj)new) | type_ListPointer;
968
969         /* And count this cell. */
970         length++;
971     } while (LowtagOf(thing) == type_ListPointer &&
972              dynamic_pointer_p(thing) &&
973              !(forwarding_pointer_p(*(lispobj *)PTR(thing))));
974
975     /* Scavenge the list we just copied. */
976     pscav((lispobj *)orig, length * WORDS_PER_CONS, constant);
977
978     return ((lispobj)orig) | type_ListPointer;
979 }
980
981 static lispobj
982 ptrans_otherptr(lispobj thing, lispobj header, boolean constant)
983 {
984     switch (TypeOf(header)) {
985       case type_Bignum:
986       case type_SingleFloat:
987       case type_DoubleFloat:
988 #ifdef type_LongFloat
989       case type_LongFloat:
990 #endif
991 #ifdef type_ComplexSingleFloat
992       case type_ComplexSingleFloat:
993 #endif
994 #ifdef type_ComplexDoubleFloat
995       case type_ComplexDoubleFloat:
996 #endif
997 #ifdef type_ComplexLongFloat
998       case type_ComplexLongFloat:
999 #endif
1000       case type_Sap:
1001         return ptrans_unboxed(thing, header);
1002
1003       case type_Ratio:
1004       case type_Complex:
1005       case type_SimpleArray:
1006       case type_ComplexString:
1007       case type_ComplexVector:
1008       case type_ComplexArray:
1009         return ptrans_boxed(thing, header, constant);
1010         
1011       case type_ValueCellHeader:
1012       case type_WeakPointer:
1013         return ptrans_boxed(thing, header, 0);
1014
1015       case type_SymbolHeader:
1016         return ptrans_boxed(thing, header, 0);
1017
1018       case type_SimpleString:
1019         return ptrans_vector(thing, 8, 1, 0, constant);
1020
1021       case type_SimpleBitVector:
1022         return ptrans_vector(thing, 1, 0, 0, constant);
1023
1024       case type_SimpleVector:
1025         return ptrans_vector(thing, 32, 0, 1, constant);
1026
1027       case type_SimpleArrayUnsignedByte2:
1028         return ptrans_vector(thing, 2, 0, 0, constant);
1029
1030       case type_SimpleArrayUnsignedByte4:
1031         return ptrans_vector(thing, 4, 0, 0, constant);
1032
1033       case type_SimpleArrayUnsignedByte8:
1034 #ifdef type_SimpleArraySignedByte8
1035       case type_SimpleArraySignedByte8:
1036 #endif
1037         return ptrans_vector(thing, 8, 0, 0, constant);
1038
1039       case type_SimpleArrayUnsignedByte16:
1040 #ifdef type_SimpleArraySignedByte16
1041       case type_SimpleArraySignedByte16:
1042 #endif
1043         return ptrans_vector(thing, 16, 0, 0, constant);
1044
1045       case type_SimpleArrayUnsignedByte32:
1046 #ifdef type_SimpleArraySignedByte30
1047       case type_SimpleArraySignedByte30:
1048 #endif
1049 #ifdef type_SimpleArraySignedByte32
1050       case type_SimpleArraySignedByte32:
1051 #endif
1052         return ptrans_vector(thing, 32, 0, 0, constant);
1053
1054       case type_SimpleArraySingleFloat:
1055         return ptrans_vector(thing, 32, 0, 0, constant);
1056
1057       case type_SimpleArrayDoubleFloat:
1058         return ptrans_vector(thing, 64, 0, 0, constant);
1059
1060 #ifdef type_SimpleArrayLongFloat
1061       case type_SimpleArrayLongFloat:
1062 #ifdef __i386__
1063         return ptrans_vector(thing, 96, 0, 0, constant);
1064 #endif
1065 #ifdef sparc
1066         return ptrans_vector(thing, 128, 0, 0, constant);
1067 #endif
1068 #endif
1069
1070 #ifdef type_SimpleArrayComplexSingleFloat
1071       case type_SimpleArrayComplexSingleFloat:
1072         return ptrans_vector(thing, 64, 0, 0, constant);
1073 #endif
1074
1075 #ifdef type_SimpleArrayComplexDoubleFloat
1076       case type_SimpleArrayComplexDoubleFloat:
1077         return ptrans_vector(thing, 128, 0, 0, constant);
1078 #endif
1079
1080 #ifdef type_SimpleArrayComplexLongFloat
1081       case type_SimpleArrayComplexLongFloat:
1082 #ifdef __i386__
1083         return ptrans_vector(thing, 192, 0, 0, constant);
1084 #endif
1085 #ifdef sparc
1086         return ptrans_vector(thing, 256, 0, 0, constant);
1087 #endif
1088 #endif
1089
1090       case type_CodeHeader:
1091         return ptrans_code(thing);
1092
1093       case type_ReturnPcHeader:
1094         return ptrans_returnpc(thing, header);
1095
1096       case type_Fdefn:
1097         return ptrans_fdefn(thing, header);
1098
1099       default:
1100         /* Should only come across other pointers to the above stuff. */
1101         gc_abort();
1102         return NIL;
1103     }
1104 }
1105
1106 static int
1107 pscav_fdefn(struct fdefn *fdefn)
1108 {
1109     boolean fix_func;
1110
1111     fix_func = ((char *)(fdefn->function+RAW_ADDR_OFFSET) == fdefn->raw_addr);
1112     pscav(&fdefn->name, 1, 1);
1113     pscav(&fdefn->function, 1, 0);
1114     if (fix_func)
1115         fdefn->raw_addr = (char *)(fdefn->function + RAW_ADDR_OFFSET);
1116     return sizeof(struct fdefn) / sizeof(lispobj);
1117 }
1118
1119 #ifdef __i386__
1120 /* now putting code objects in static space */
1121 static int
1122 pscav_code(struct code*code)
1123 {
1124     int nwords;
1125     lispobj func;
1126     nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
1127
1128     /* pw--The trace_table_offset slot can contain a list pointer. This
1129      * occurs when the code object is a top level form that initializes
1130      * a byte-compiled function. The fact that PURIFY was ignoring this
1131      * slot may be a bug unrelated to the x86 port, except that TLF's
1132      * normally become unreachable after the loader calls them and
1133      * won't be seen by PURIFY at all!! */
1134     if(code->trace_table_offset & 0x3)
1135 #if 0
1136       pscav(&code->trace_table_offset, 1, 0);
1137 #else
1138       code->trace_table_offset = NIL; /* limit lifetime */
1139 #endif
1140
1141     /* Arrange to scavenge the debug info later. */
1142     pscav_later(&code->debug_info, 1);
1143
1144     /* Scavenge the constants. */
1145     pscav(code->constants, HeaderValue(code->header)-5, 1);
1146
1147     /* Scavenge all the functions. */
1148     pscav(&code->entry_points, 1, 1);
1149     for (func = code->entry_points;
1150          func != NIL;
1151          func = ((struct function *)PTR(func))->next) {
1152         gc_assert(LowtagOf(func) == type_FunctionPointer);
1153         gc_assert(!dynamic_pointer_p(func));
1154
1155 #ifdef __i386__
1156         /* Temporarly convert the self pointer to a real function
1157          * pointer. */
1158         ((struct function *)PTR(func))->self -= RAW_ADDR_OFFSET;
1159 #endif
1160         pscav(&((struct function *)PTR(func))->self, 2, 1);
1161 #ifdef __i386__
1162         ((struct function *)PTR(func))->self += RAW_ADDR_OFFSET;
1163 #endif
1164         pscav_later(&((struct function *)PTR(func))->name, 3);
1165     }
1166
1167     return CEILING(nwords,2);
1168 }
1169 #endif
1170
1171 static lispobj *
1172 pscav(lispobj *addr, int nwords, boolean constant)
1173 {
1174     lispobj thing, *thingp, header;
1175     int count = 0; /* (0 = dummy init value to stop GCC warning) */
1176     struct vector *vector;
1177
1178     while (nwords > 0) {
1179         thing = *addr;
1180         if (Pointerp(thing)) {
1181             /* It's a pointer. Is it something we might have to move? */
1182             if (dynamic_pointer_p(thing)) {
1183                 /* Maybe. Have we already moved it? */
1184                 thingp = (lispobj *)PTR(thing);
1185                 header = *thingp;
1186                 if (Pointerp(header) && forwarding_pointer_p(header))
1187                     /* Yep, so just copy the forwarding pointer. */
1188                     thing = header;
1189                 else {
1190                     /* Nope, copy the object. */
1191                     switch (LowtagOf(thing)) {
1192                       case type_FunctionPointer:
1193                         thing = ptrans_func(thing, header);
1194                         break;
1195
1196                       case type_ListPointer:
1197                         thing = ptrans_list(thing, constant);
1198                         break;
1199
1200                       case type_InstancePointer:
1201                         thing = ptrans_instance(thing, header, constant);
1202                         break;
1203
1204                       case type_OtherPointer:
1205                         thing = ptrans_otherptr(thing, header, constant);
1206                         break;
1207
1208                       default:
1209                         /* It was a pointer, but not one of them? */
1210                         gc_abort();
1211                     }
1212                 }
1213                 *addr = thing;
1214             }
1215             count = 1;
1216         }
1217         else if (thing & 3) {
1218             /* It's an other immediate. Maybe the header for an unboxed */
1219             /* object. */
1220             switch (TypeOf(thing)) {
1221               case type_Bignum:
1222               case type_SingleFloat:
1223               case type_DoubleFloat:
1224 #ifdef type_LongFloat
1225               case type_LongFloat:
1226 #endif
1227               case type_Sap:
1228                 /* It's an unboxed simple object. */
1229                 count = HeaderValue(thing)+1;
1230                 break;
1231
1232               case type_SimpleVector:
1233                 if (HeaderValue(thing) == subtype_VectorValidHashing)
1234                     *addr = (subtype_VectorMustRehash<<type_Bits) |
1235                         type_SimpleVector;
1236                 count = 1;
1237                 break;
1238
1239               case type_SimpleString:
1240                 vector = (struct vector *)addr;
1241                 count = CEILING(NWORDS(fixnum_value(vector->length)+1,4)+2,2);
1242                 break;
1243
1244               case type_SimpleBitVector:
1245                 vector = (struct vector *)addr;
1246                 count = CEILING(NWORDS(fixnum_value(vector->length),32)+2,2);
1247                 break;
1248
1249               case type_SimpleArrayUnsignedByte2:
1250                 vector = (struct vector *)addr;
1251                 count = CEILING(NWORDS(fixnum_value(vector->length),16)+2,2);
1252                 break;
1253
1254               case type_SimpleArrayUnsignedByte4:
1255                 vector = (struct vector *)addr;
1256                 count = CEILING(NWORDS(fixnum_value(vector->length),8)+2,2);
1257                 break;
1258
1259               case type_SimpleArrayUnsignedByte8:
1260 #ifdef type_SimpleArraySignedByte8
1261               case type_SimpleArraySignedByte8:
1262 #endif
1263                 vector = (struct vector *)addr;
1264                 count = CEILING(NWORDS(fixnum_value(vector->length),4)+2,2);
1265                 break;
1266
1267               case type_SimpleArrayUnsignedByte16:
1268 #ifdef type_SimpleArraySignedByte16
1269               case type_SimpleArraySignedByte16:
1270 #endif
1271                 vector = (struct vector *)addr;
1272                 count = CEILING(NWORDS(fixnum_value(vector->length),2)+2,2);
1273                 break;
1274
1275               case type_SimpleArrayUnsignedByte32:
1276 #ifdef type_SimpleArraySignedByte30
1277               case type_SimpleArraySignedByte30:
1278 #endif
1279 #ifdef type_SimpleArraySignedByte32
1280               case type_SimpleArraySignedByte32:
1281 #endif
1282                 vector = (struct vector *)addr;
1283                 count = CEILING(fixnum_value(vector->length)+2,2);
1284                 break;
1285
1286               case type_SimpleArraySingleFloat:
1287                 vector = (struct vector *)addr;
1288                 count = CEILING(fixnum_value(vector->length)+2,2);
1289                 break;
1290
1291               case type_SimpleArrayDoubleFloat:
1292 #ifdef type_SimpleArrayComplexSingleFloat
1293               case type_SimpleArrayComplexSingleFloat:
1294 #endif
1295                 vector = (struct vector *)addr;
1296                 count = fixnum_value(vector->length)*2+2;
1297                 break;
1298
1299 #ifdef type_SimpleArrayLongFloat
1300               case type_SimpleArrayLongFloat:
1301                 vector = (struct vector *)addr;
1302 #ifdef __i386__
1303                 count = fixnum_value(vector->length)*3+2;
1304 #endif
1305 #ifdef sparc
1306                 count = fixnum_value(vector->length)*4+2;
1307 #endif
1308                 break;
1309 #endif
1310
1311 #ifdef type_SimpleArrayComplexDoubleFloat
1312               case type_SimpleArrayComplexDoubleFloat:
1313                 vector = (struct vector *)addr;
1314                 count = fixnum_value(vector->length)*4+2;
1315                 break;
1316 #endif
1317
1318 #ifdef type_SimpleArrayComplexLongFloat
1319               case type_SimpleArrayComplexLongFloat:
1320                 vector = (struct vector *)addr;
1321 #ifdef __i386__
1322                 count = fixnum_value(vector->length)*6+2;
1323 #endif
1324 #ifdef sparc
1325                 count = fixnum_value(vector->length)*8+2;
1326 #endif
1327                 break;
1328 #endif
1329
1330               case type_CodeHeader:
1331 #ifndef __i386__
1332                 gc_abort(); /* no code headers in static space */
1333 #else
1334                 count = pscav_code((struct code*)addr);
1335 #endif
1336                 break;
1337
1338               case type_FunctionHeader:
1339               case type_ClosureFunctionHeader:
1340               case type_ReturnPcHeader:
1341                 /* We should never hit any of these, 'cause they occur
1342                  * buried in the middle of code objects. */
1343                 gc_abort();
1344                 break;
1345
1346 #ifdef __i386__
1347               case type_ClosureHeader:
1348               case type_FuncallableInstanceHeader:
1349               case type_ByteCodeFunction:
1350               case type_ByteCodeClosure:
1351                 /* The function self pointer needs special care on the
1352                  * x86 because it is the real entry point. */
1353                 {
1354                   lispobj fun = ((struct closure *)addr)->function
1355                     - RAW_ADDR_OFFSET;
1356                   pscav(&fun, 1, constant);
1357                   ((struct closure *)addr)->function = fun + RAW_ADDR_OFFSET;
1358                 }
1359                 count = 2;
1360                 break;
1361 #endif
1362
1363               case type_WeakPointer:
1364                 /* Weak pointers get preserved during purify, 'cause I
1365                  * don't feel like figuring out how to break them. */
1366                 pscav(addr+1, 2, constant);
1367                 count = 4;
1368                 break;
1369
1370               case type_Fdefn:
1371                 /* We have to handle fdefn objects specially, so we
1372                  * can fix up the raw function address. */
1373                 count = pscav_fdefn((struct fdefn *)addr);
1374                 break;
1375
1376               default:
1377                 count = 1;
1378                 break;
1379             }
1380         }
1381         else {
1382             /* It's a fixnum. */
1383             count = 1;
1384         }
1385
1386         addr += count;
1387         nwords -= count;
1388     }
1389
1390     return addr;
1391 }
1392
1393 int
1394 purify(lispobj static_roots, lispobj read_only_roots)
1395 {
1396     lispobj *clean;
1397     int count, i;
1398     struct later *laters, *next;
1399
1400 #ifdef PRINTNOISE
1401     printf("[doing purification:");
1402     fflush(stdout);
1403 #endif
1404
1405     if (fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX)) != 0) {
1406         /* FIXME: 1. What does this mean? 2. It shouldn't be reporting
1407          * its error simply by a. printing a string b. to stdout instead
1408          * of stderr. */
1409         printf(" Ack! Can't purify interrupt contexts. ");
1410         fflush(stdout);
1411         return 0;
1412     }
1413
1414 #if defined(ibmrt) || defined(__i386__)
1415     dynamic_space_free_pointer =
1416       (lispobj*)SymbolValue(ALLOCATION_POINTER);
1417 #endif
1418
1419     read_only_end = read_only_free =
1420         (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER);
1421     static_end = static_free =
1422         (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER);
1423
1424 #ifdef PRINTNOISE
1425     printf(" roots");
1426     fflush(stdout);
1427 #endif
1428
1429 #ifdef GENCGC
1430     gc_assert((lispobj *)CONTROL_STACK_END > ((&read_only_roots)+1));
1431     setup_i386_stack_scav(((&static_roots)-2), (lispobj *)CONTROL_STACK_END);
1432 #endif
1433
1434     pscav(&static_roots, 1, 0);
1435     pscav(&read_only_roots, 1, 1);
1436
1437 #ifdef PRINTNOISE
1438     printf(" handlers");
1439     fflush(stdout);
1440 #endif
1441     pscav((lispobj *) interrupt_handlers,
1442           sizeof(interrupt_handlers) / sizeof(lispobj),
1443           0);
1444
1445 #ifdef PRINTNOISE
1446     printf(" stack");
1447     fflush(stdout);
1448 #endif
1449 #ifndef __i386__
1450     pscav((lispobj *)CONTROL_STACK_START,
1451           current_control_stack_pointer - (lispobj *)CONTROL_STACK_START,
1452           0);
1453 #else
1454 #ifdef GENCGC
1455     pscav_i386_stack();
1456 #endif
1457 #ifdef WANT_CGC
1458     gc_assert((lispobj *)control_stack_end > ((&read_only_roots)+1));
1459     carefully_pscav_stack(((&read_only_roots)+1),
1460                           (lispobj *)CONTROL_STACK_END);
1461 #endif
1462 #endif
1463
1464 #ifdef PRINTNOISE
1465     printf(" bindings");
1466     fflush(stdout);
1467 #endif
1468 #if !defined(ibmrt) && !defined(__i386__)
1469     pscav((lispobj *)BINDING_STACK_START,
1470           (lispobj *)current_binding_stack_pointer
1471           - (lispobj *)BINDING_STACK_START,
1472           0);
1473 #else
1474     pscav( (lispobj *)BINDING_STACK_START,
1475           (lispobj *)SymbolValue(BINDING_STACK_POINTER) -
1476           (lispobj *)BINDING_STACK_START,
1477           0);
1478 #endif
1479
1480 #ifdef SCAVENGE_READ_ONLY_SPACE
1481     if (SymbolValue(SCAVENGE_READ_ONLY_SPACE) != type_UnboundMarker
1482         && SymbolValue(SCAVENGE_READ_ONLY_SPACE) != NIL) {
1483         unsigned  read_only_space_size =
1484             (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) -
1485             (lispobj *)READ_ONLY_SPACE_START;
1486         fprintf(stderr,
1487                 "scavenging read only space: %d bytes\n",
1488                 read_only_space_size * sizeof(lispobj));
1489         pscav( (lispobj *)READ_ONLY_SPACE_START, read_only_space_size, 0);
1490     }
1491 #endif
1492
1493 #ifdef PRINTNOISE
1494     printf(" static");
1495     fflush(stdout);
1496 #endif
1497     clean = (lispobj *)STATIC_SPACE_START;
1498     do {
1499         while (clean != static_free)
1500             clean = pscav(clean, static_free - clean, 0);
1501         laters = later_blocks;
1502         count = later_count;
1503         later_blocks = NULL;
1504         later_count = 0;
1505         while (laters != NULL) {
1506             for (i = 0; i < count; i++) {
1507                 if (laters->u[i].count == 0) {
1508                     ;
1509                 } else if (laters->u[i].count <= LATERMAXCOUNT) {
1510                     pscav(laters->u[i+1].ptr, laters->u[i].count, 1);
1511                     i++;
1512                 } else {
1513                     pscav(laters->u[i].ptr, 1, 1);
1514                 }
1515             }
1516             next = laters->next;
1517             free(laters);
1518             laters = next;
1519             count = LATERBLOCKSIZE;
1520         }
1521     } while (clean != static_free || later_blocks != NULL);
1522
1523 #ifdef PRINTNOISE
1524     printf(" cleanup");
1525     fflush(stdout);
1526 #endif
1527
1528 #if defined(WANT_CGC) && defined(X86_CGC_ACTIVE_P)
1529     if(SymbolValue(X86_CGC_ACTIVE_P) != T) {
1530         os_zero((os_vm_address_t) DYNAMIC_SPACE_START,
1531                 (os_vm_size_t) DYNAMIC_SPACE_SIZE);
1532     }
1533 #else
1534     os_zero((os_vm_address_t) current_dynamic_space,
1535             (os_vm_size_t) DYNAMIC_SPACE_SIZE);
1536 #endif
1537
1538     /* Zero the stack. Note that the stack is also zeroed by SUB-GC
1539      * calling SCRUB-CONTROL-STACK - this zeros the stack on the x86. */
1540 #ifndef __i386__
1541     os_zero((os_vm_address_t) current_control_stack_pointer,
1542             (os_vm_size_t) (CONTROL_STACK_SIZE -
1543                             ((current_control_stack_pointer -
1544                               (lispobj *)CONTROL_STACK_START) *
1545                              sizeof(lispobj))));
1546 #endif
1547
1548 #if defined(WANT_CGC) && defined(STATIC_BLUE_BAG)
1549     {
1550         lispobj bag = SymbolValue(STATIC_BLUE_BAG);
1551         struct cons *cons = (struct cons*)static_free;
1552         struct cons *pair = cons + 1;
1553         static_free += 2 * WORDS_PER_CONS;
1554         if(bag == type_UnboundMarker)
1555             bag = NIL;
1556         cons->cdr = bag;
1557         cons->car = (lispobj)pair | type_ListPointer;
1558         pair->car = (lispobj)static_end;
1559         pair->cdr = (lispobj)static_free;
1560         bag = (lispobj)cons | type_ListPointer;
1561         SetSymbolValue(STATIC_BLUE_BAG, bag);
1562     }
1563 #endif
1564
1565     /* It helps to update the heap free pointers so that free_heap()
1566      * can verify after it's done. */
1567     SetSymbolValue(READ_ONLY_SPACE_FREE_POINTER, (lispobj)read_only_free);
1568     SetSymbolValue(STATIC_SPACE_FREE_POINTER, (lispobj)static_free);
1569
1570 #if !defined(ibmrt) && !defined(__i386__)
1571     dynamic_space_free_pointer = current_dynamic_space;
1572 #else
1573 #if defined(WANT_CGC) && defined(X86_CGC_ACTIVE_P)
1574     /* X86 using CGC */
1575     if(SymbolValue(X86_CGC_ACTIVE_P) != T)
1576         SetSymbolValue(ALLOCATION_POINTER, (lispobj)DYNAMIC_SPACE_START);
1577     else
1578         cgc_free_heap();
1579 #else
1580 #if defined(GENCGC)
1581     gc_free_heap();
1582 #else
1583     /* ibmrt using GC */
1584     SetSymbolValue(ALLOCATION_POINTER, (lispobj)DYNAMIC_SPACE_START);
1585 #endif
1586 #endif
1587 #endif
1588
1589 #ifdef PRINTNOISE
1590     printf(" done]\n");
1591     fflush(stdout);
1592 #endif
1593
1594     return 0;
1595 }