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