9e8159a93394f368685d18ea53355f3fa2c780aa
[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     /* "why" is a hard word, but apparently for compiled functions the
739        trace_table_offset contains the length of the instructions, as
740        a fixnum.  See CODE-INST-AREA-LENGTH in
741        src/compiler/target-disassem.lisp.  -- CSR, 2004-01-08 */
742     if (!(fixnump(new->trace_table_offset)))
743 #if 0
744         pscav(&new->trace_table_offset, 1, 0);
745 #else
746         new->trace_table_offset = NIL; /* limit lifetime */
747 #endif
748
749     /* Scavenge the constants. */
750     pscav(new->constants, HeaderValue(new->header)-5, 1);
751
752     /* Scavenge all the functions. */
753     pscav(&new->entry_points, 1, 1);
754     for (func = new->entry_points;
755          func != NIL;
756          func = ((struct simple_fun *)native_pointer(func))->next) {
757         gc_assert(lowtag_of(func) == FUN_POINTER_LOWTAG);
758         gc_assert(!dynamic_pointer_p(func));
759
760 #ifdef LISP_FEATURE_X86
761         /* Temporarily convert the self pointer to a real function pointer. */
762         ((struct simple_fun *)native_pointer(func))->self
763             -= FUN_RAW_ADDR_OFFSET;
764 #endif
765         pscav(&((struct simple_fun *)native_pointer(func))->self, 2, 1);
766 #ifdef LISP_FEATURE_X86
767         ((struct simple_fun *)native_pointer(func))->self
768             += FUN_RAW_ADDR_OFFSET;
769 #endif
770         pscav_later(&((struct simple_fun *)native_pointer(func))->name, 3);
771     }
772
773     return result;
774 }
775
776 static lispobj
777 ptrans_func(lispobj thing, lispobj header)
778 {
779     int nwords;
780     lispobj code, *new, *old, result;
781     struct simple_fun *function;
782
783     /* Thing can either be a function header, a closure function
784      * header, a closure, or a funcallable-instance. If it's a closure
785      * or a funcallable-instance, we do the same as ptrans_boxed.
786      * Otherwise we have to do something strange, 'cause it is buried
787      * inside a code object. */
788
789     if (widetag_of(header) == SIMPLE_FUN_HEADER_WIDETAG) {
790
791         /* We can only end up here if the code object has not been
792          * scavenged, because if it had been scavenged, forwarding pointers
793          * would have been left behind for all the entry points. */
794
795         function = (struct simple_fun *)native_pointer(thing);
796         code =
797             make_lispobj
798             ((native_pointer(thing) -
799               (HeaderValue(function->header))), OTHER_POINTER_LOWTAG);
800         
801         /* This will cause the function's header to be replaced with a 
802          * forwarding pointer. */
803
804         ptrans_code(code);
805
806         /* So we can just return that. */
807         return function->header;
808     }
809     else {
810         /* It's some kind of closure-like thing. */
811         nwords = 1 + HeaderValue(header);
812         old = (lispobj *)native_pointer(thing);
813
814         /* Allocate the new one.  FINs *must* not go in read_only
815          * space.  Closures can; they never change */
816
817         new = newspace_alloc
818             (nwords,(widetag_of(header)!=FUNCALLABLE_INSTANCE_HEADER_WIDETAG));
819              
820         /* Copy it. */
821         bcopy(old, new, nwords * sizeof(lispobj));
822
823         /* Deposit forwarding pointer. */
824         result = make_lispobj(new, lowtag_of(thing));
825         *old = result;
826
827         /* Scavenge it. */
828         pscav(new, nwords, 0);
829
830         return result;
831     }
832 }
833
834 static lispobj
835 ptrans_returnpc(lispobj thing, lispobj header)
836 {
837     lispobj code, new;
838
839     /* Find the corresponding code object. */
840     code = thing - HeaderValue(header)*sizeof(lispobj);
841
842     /* Make sure it's been transported. */
843     new = *(lispobj *)native_pointer(code);
844     if (!forwarding_pointer_p(new))
845         new = ptrans_code(code);
846
847     /* Maintain the offset: */
848     return new + (thing - code);
849 }
850
851 #define WORDS_PER_CONS CEILING(sizeof(struct cons) / sizeof(lispobj), 2)
852
853 static lispobj
854 ptrans_list(lispobj thing, boolean constant)
855 {
856     struct cons *old, *new, *orig;
857     int length;
858
859     orig = newspace_alloc(0,constant);
860     length = 0;
861
862     do {
863         /* Allocate a new cons cell. */
864         old = (struct cons *)native_pointer(thing);
865         new = (struct cons *) newspace_alloc(WORDS_PER_CONS,constant);
866
867         /* Copy the cons cell and keep a pointer to the cdr. */
868         new->car = old->car;
869         thing = new->cdr = old->cdr;
870
871         /* Set up the forwarding pointer. */
872         *(lispobj *)old = make_lispobj(new, LIST_POINTER_LOWTAG);
873
874         /* And count this cell. */
875         length++;
876     } while (lowtag_of(thing) == LIST_POINTER_LOWTAG &&
877              dynamic_pointer_p(thing) &&
878              !(forwarding_pointer_p(*(lispobj *)native_pointer(thing))));
879
880     /* Scavenge the list we just copied. */
881     pscav((lispobj *)orig, length * WORDS_PER_CONS, constant);
882
883     return make_lispobj(orig, LIST_POINTER_LOWTAG);
884 }
885
886 static lispobj
887 ptrans_otherptr(lispobj thing, lispobj header, boolean constant)
888 {
889     switch (widetag_of(header)) {
890         /* FIXME: this needs a reindent */
891       case BIGNUM_WIDETAG:
892       case SINGLE_FLOAT_WIDETAG:
893       case DOUBLE_FLOAT_WIDETAG:
894 #ifdef LONG_FLOAT_WIDETAG
895       case LONG_FLOAT_WIDETAG:
896 #endif
897 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
898       case COMPLEX_SINGLE_FLOAT_WIDETAG:
899 #endif
900 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
901       case COMPLEX_DOUBLE_FLOAT_WIDETAG:
902 #endif
903 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
904       case COMPLEX_LONG_FLOAT_WIDETAG:
905 #endif
906       case SAP_WIDETAG:
907           return ptrans_unboxed(thing, header);
908
909       case RATIO_WIDETAG:
910       case COMPLEX_WIDETAG:
911       case SIMPLE_ARRAY_WIDETAG:
912       case COMPLEX_BASE_STRING_WIDETAG:
913       case COMPLEX_BIT_VECTOR_WIDETAG:
914       case COMPLEX_VECTOR_NIL_WIDETAG:
915       case COMPLEX_VECTOR_WIDETAG:
916       case COMPLEX_ARRAY_WIDETAG:
917         return ptrans_boxed(thing, header, constant);
918         
919       case VALUE_CELL_HEADER_WIDETAG:
920       case WEAK_POINTER_WIDETAG:
921         return ptrans_boxed(thing, header, 0);
922
923       case SYMBOL_HEADER_WIDETAG:
924         return ptrans_boxed(thing, header, 0);
925
926       case SIMPLE_ARRAY_NIL_WIDETAG:
927         return ptrans_vector(thing, 0, 0, 0, constant);
928
929       case SIMPLE_BASE_STRING_WIDETAG:
930         return ptrans_vector(thing, 8, 1, 0, constant);
931
932       case SIMPLE_BIT_VECTOR_WIDETAG:
933         return ptrans_vector(thing, 1, 0, 0, constant);
934
935       case SIMPLE_VECTOR_WIDETAG:
936         return ptrans_vector(thing, 32, 0, 1, constant);
937
938       case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
939         return ptrans_vector(thing, 2, 0, 0, constant);
940
941       case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
942         return ptrans_vector(thing, 4, 0, 0, constant);
943
944       case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
945 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
946       case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
947       case SIMPLE_ARRAY_UNSIGNED_BYTE_7_WIDETAG:
948 #endif
949         return ptrans_vector(thing, 8, 0, 0, constant);
950
951       case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
952 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
953       case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
954       case SIMPLE_ARRAY_UNSIGNED_BYTE_15_WIDETAG:
955 #endif
956         return ptrans_vector(thing, 16, 0, 0, constant);
957
958       case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
959 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
960       case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
961       case SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG:
962 #endif
963 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
964       case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
965       case SIMPLE_ARRAY_UNSIGNED_BYTE_31_WIDETAG:
966 #endif
967         return ptrans_vector(thing, 32, 0, 0, constant);
968
969       case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
970         return ptrans_vector(thing, 32, 0, 0, constant);
971
972       case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
973         return ptrans_vector(thing, 64, 0, 0, constant);
974
975 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
976       case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
977 #ifdef LISP_FEATURE_X86
978         return ptrans_vector(thing, 96, 0, 0, constant);
979 #endif
980 #ifdef sparc
981         return ptrans_vector(thing, 128, 0, 0, constant);
982 #endif
983 #endif
984
985 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
986       case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
987         return ptrans_vector(thing, 64, 0, 0, constant);
988 #endif
989
990 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
991       case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
992         return ptrans_vector(thing, 128, 0, 0, constant);
993 #endif
994
995 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
996       case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
997 #ifdef LISP_FEATURE_X86
998         return ptrans_vector(thing, 192, 0, 0, constant);
999 #endif
1000 #ifdef sparc
1001         return ptrans_vector(thing, 256, 0, 0, constant);
1002 #endif
1003 #endif
1004
1005       case CODE_HEADER_WIDETAG:
1006         return ptrans_code(thing);
1007
1008       case RETURN_PC_HEADER_WIDETAG:
1009         return ptrans_returnpc(thing, header);
1010
1011       case FDEFN_WIDETAG:
1012         return ptrans_fdefn(thing, header);
1013
1014       default:
1015         /* Should only come across other pointers to the above stuff. */
1016         gc_abort();
1017         return NIL;
1018     }
1019 }
1020
1021 static int
1022 pscav_fdefn(struct fdefn *fdefn)
1023 {
1024     boolean fix_func;
1025
1026     fix_func = ((char *)(fdefn->fun+FUN_RAW_ADDR_OFFSET) == fdefn->raw_addr);
1027     pscav(&fdefn->name, 1, 1);
1028     pscav(&fdefn->fun, 1, 0);
1029     if (fix_func)
1030         fdefn->raw_addr = (char *)(fdefn->fun + FUN_RAW_ADDR_OFFSET);
1031     return sizeof(struct fdefn) / sizeof(lispobj);
1032 }
1033
1034 #ifdef LISP_FEATURE_X86
1035 /* now putting code objects in static space */
1036 static int
1037 pscav_code(struct code*code)
1038 {
1039     int nwords;
1040     lispobj func;
1041     nwords = HeaderValue(code->header) + fixnum_value(code->code_size);
1042
1043     /* Arrange to scavenge the debug info later. */
1044     pscav_later(&code->debug_info, 1);
1045
1046     /* Scavenge the constants. */
1047     pscav(code->constants, HeaderValue(code->header)-5, 1);
1048
1049     /* Scavenge all the functions. */
1050     pscav(&code->entry_points, 1, 1);
1051     for (func = code->entry_points;
1052          func != NIL;
1053          func = ((struct simple_fun *)native_pointer(func))->next) {
1054         gc_assert(lowtag_of(func) == FUN_POINTER_LOWTAG);
1055         gc_assert(!dynamic_pointer_p(func));
1056
1057 #ifdef LISP_FEATURE_X86
1058         /* Temporarily convert the self pointer to a real function
1059          * pointer. */
1060         ((struct simple_fun *)native_pointer(func))->self
1061             -= FUN_RAW_ADDR_OFFSET;
1062 #endif
1063         pscav(&((struct simple_fun *)native_pointer(func))->self, 2, 1);
1064 #ifdef LISP_FEATURE_X86
1065         ((struct simple_fun *)native_pointer(func))->self
1066             += FUN_RAW_ADDR_OFFSET;
1067 #endif
1068         pscav_later(&((struct simple_fun *)native_pointer(func))->name, 3);
1069     }
1070
1071     return CEILING(nwords,2);
1072 }
1073 #endif
1074
1075 static lispobj *
1076 pscav(lispobj *addr, int nwords, boolean constant)
1077 {
1078     lispobj thing, *thingp, header;
1079     int count = 0; /* (0 = dummy init value to stop GCC warning) */
1080     struct vector *vector;
1081
1082     while (nwords > 0) {
1083         thing = *addr;
1084         if (is_lisp_pointer(thing)) {
1085             /* It's a pointer. Is it something we might have to move? */
1086             if (dynamic_pointer_p(thing)) {
1087                 /* Maybe. Have we already moved it? */
1088                 thingp = (lispobj *)native_pointer(thing);
1089                 header = *thingp;
1090                 if (is_lisp_pointer(header) && forwarding_pointer_p(header))
1091                     /* Yep, so just copy the forwarding pointer. */
1092                     thing = header;
1093                 else {
1094                     /* Nope, copy the object. */
1095                     switch (lowtag_of(thing)) {
1096                       case FUN_POINTER_LOWTAG:
1097                         thing = ptrans_func(thing, header);
1098                         break;
1099
1100                       case LIST_POINTER_LOWTAG:
1101                         thing = ptrans_list(thing, constant);
1102                         break;
1103
1104                       case INSTANCE_POINTER_LOWTAG:
1105                         thing = ptrans_instance(thing, header, constant);
1106                         break;
1107
1108                       case OTHER_POINTER_LOWTAG:
1109                         thing = ptrans_otherptr(thing, header, constant);
1110                         break;
1111
1112                       default:
1113                         /* It was a pointer, but not one of them? */
1114                         gc_abort();
1115                     }
1116                 }
1117                 *addr = thing;
1118             }
1119             count = 1;
1120         }
1121         else if (thing & 3) {   /* FIXME: 3?  not 2? */
1122             /* It's an other immediate. Maybe the header for an unboxed */
1123             /* object. */
1124             switch (widetag_of(thing)) {
1125               case BIGNUM_WIDETAG:
1126               case SINGLE_FLOAT_WIDETAG:
1127               case DOUBLE_FLOAT_WIDETAG:
1128 #ifdef LONG_FLOAT_WIDETAG
1129               case LONG_FLOAT_WIDETAG:
1130 #endif
1131               case SAP_WIDETAG:
1132                 /* It's an unboxed simple object. */
1133                 count = HeaderValue(thing)+1;
1134                 break;
1135
1136               case SIMPLE_VECTOR_WIDETAG:
1137                   if (HeaderValue(thing) == subtype_VectorValidHashing) {
1138                     *addr = (subtype_VectorMustRehash << N_WIDETAG_BITS) |
1139                         SIMPLE_VECTOR_WIDETAG;
1140                   }
1141                 count = 1;
1142                 break;
1143
1144               case SIMPLE_ARRAY_NIL_WIDETAG:
1145                 count = 2;
1146                 break;
1147
1148               case SIMPLE_BASE_STRING_WIDETAG:
1149                 vector = (struct vector *)addr;
1150                 count = CEILING(NWORDS(fixnum_value(vector->length)+1,4)+2,2);
1151                 break;
1152
1153               case SIMPLE_BIT_VECTOR_WIDETAG:
1154                 vector = (struct vector *)addr;
1155                 count = CEILING(NWORDS(fixnum_value(vector->length),32)+2,2);
1156                 break;
1157
1158               case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
1159                 vector = (struct vector *)addr;
1160                 count = CEILING(NWORDS(fixnum_value(vector->length),16)+2,2);
1161                 break;
1162
1163               case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
1164                 vector = (struct vector *)addr;
1165                 count = CEILING(NWORDS(fixnum_value(vector->length),8)+2,2);
1166                 break;
1167
1168               case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
1169 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
1170               case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
1171               case SIMPLE_ARRAY_UNSIGNED_BYTE_7_WIDETAG:
1172 #endif
1173                 vector = (struct vector *)addr;
1174                 count = CEILING(NWORDS(fixnum_value(vector->length),4)+2,2);
1175                 break;
1176
1177               case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
1178 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
1179               case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
1180               case SIMPLE_ARRAY_UNSIGNED_BYTE_15_WIDETAG:
1181 #endif
1182                 vector = (struct vector *)addr;
1183                 count = CEILING(NWORDS(fixnum_value(vector->length),2)+2,2);
1184                 break;
1185
1186               case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
1187 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
1188               case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
1189               case SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG:
1190 #endif
1191 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
1192               case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
1193               case SIMPLE_ARRAY_UNSIGNED_BYTE_31_WIDETAG:
1194 #endif
1195                 vector = (struct vector *)addr;
1196                 count = CEILING(fixnum_value(vector->length)+2,2);
1197                 break;
1198
1199               case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
1200                 vector = (struct vector *)addr;
1201                 count = CEILING(fixnum_value(vector->length)+2,2);
1202                 break;
1203
1204               case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
1205 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
1206               case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
1207 #endif
1208                 vector = (struct vector *)addr;
1209                 count = fixnum_value(vector->length)*2+2;
1210                 break;
1211
1212 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
1213               case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
1214                 vector = (struct vector *)addr;
1215 #ifdef LISP_FEATURE_X86
1216                 count = fixnum_value(vector->length)*3+2;
1217 #endif
1218 #ifdef sparc
1219                 count = fixnum_value(vector->length)*4+2;
1220 #endif
1221                 break;
1222 #endif
1223
1224 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
1225               case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
1226                 vector = (struct vector *)addr;
1227                 count = fixnum_value(vector->length)*4+2;
1228                 break;
1229 #endif
1230
1231 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
1232               case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
1233                 vector = (struct vector *)addr;
1234 #ifdef LISP_FEATURE_X86
1235                 count = fixnum_value(vector->length)*6+2;
1236 #endif
1237 #ifdef sparc
1238                 count = fixnum_value(vector->length)*8+2;
1239 #endif
1240                 break;
1241 #endif
1242
1243               case CODE_HEADER_WIDETAG:
1244 #ifndef LISP_FEATURE_X86
1245                 gc_abort(); /* no code headers in static space */
1246 #else
1247                 count = pscav_code((struct code*)addr);
1248 #endif
1249                 break;
1250
1251               case SIMPLE_FUN_HEADER_WIDETAG:
1252               case RETURN_PC_HEADER_WIDETAG:
1253                 /* We should never hit any of these, 'cause they occur
1254                  * buried in the middle of code objects. */
1255                 gc_abort();
1256                 break;
1257
1258 #ifdef LISP_FEATURE_X86
1259               case CLOSURE_HEADER_WIDETAG:
1260               case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
1261                 /* The function self pointer needs special care on the
1262                  * x86 because it is the real entry point. */
1263                 {
1264                   lispobj fun = ((struct closure *)addr)->fun
1265                     - FUN_RAW_ADDR_OFFSET;
1266                   pscav(&fun, 1, constant);
1267                   ((struct closure *)addr)->fun = fun + FUN_RAW_ADDR_OFFSET;
1268                 }
1269                 count = 2;
1270                 break;
1271 #endif
1272
1273               case WEAK_POINTER_WIDETAG:
1274                 /* Weak pointers get preserved during purify, 'cause I
1275                  * don't feel like figuring out how to break them. */
1276                 pscav(addr+1, 2, constant);
1277                 count = 4;
1278                 break;
1279
1280               case FDEFN_WIDETAG:
1281                 /* We have to handle fdefn objects specially, so we
1282                  * can fix up the raw function address. */
1283                 count = pscav_fdefn((struct fdefn *)addr);
1284                 break;
1285
1286               default:
1287                 count = 1;
1288                 break;
1289             }
1290         }
1291         else {
1292             /* It's a fixnum. */
1293             count = 1;
1294         }
1295
1296         addr += count;
1297         nwords -= count;
1298     }
1299
1300     return addr;
1301 }
1302
1303 int
1304 purify(lispobj static_roots, lispobj read_only_roots)
1305 {
1306     lispobj *clean;
1307     int count, i;
1308     struct later *laters, *next;
1309     struct thread *thread;
1310
1311     if(all_threads->next) {
1312         /* FIXME: there should be _some_ sensible error reporting 
1313          * convention.  See following comment too */
1314         fprintf(stderr,"Can't purify when more than one thread exists\n");
1315         fflush(stderr);
1316         return 0;
1317     }
1318
1319 #ifdef PRINTNOISE
1320     printf("[doing purification:");
1321     fflush(stdout);
1322 #endif
1323 #ifdef LISP_FEATURE_GENCGC
1324     gc_alloc_update_all_page_tables();
1325 #endif
1326     for_each_thread(thread)
1327         if (fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,thread)) != 0) {
1328         /* FIXME: 1. What does this mean? 2. It shouldn't be reporting
1329          * its error simply by a. printing a string b. to stdout instead
1330          * of stderr. */
1331         printf(" Ack! Can't purify interrupt contexts. ");
1332         fflush(stdout);
1333         return 0;
1334     }
1335
1336 #if defined(LISP_FEATURE_X86)
1337     dynamic_space_free_pointer =
1338       (lispobj*)SymbolValue(ALLOCATION_POINTER,0);
1339 #endif
1340
1341     read_only_end = read_only_free =
1342         (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0);
1343     static_end = static_free =
1344         (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0);
1345
1346 #ifdef PRINTNOISE
1347     printf(" roots");
1348     fflush(stdout);
1349 #endif
1350
1351 #if (defined(LISP_FEATURE_GENCGC) && defined(LISP_FEATURE_X86))
1352     /* note this expects only one thread to be active.  We'd have to 
1353      * stop all the others in the same way as GC does if we wanted 
1354      * PURIFY to work when >1 thread exists */
1355     setup_i386_stack_scav(((&static_roots)-2),
1356                           ((void *)all_threads->control_stack_end));
1357 #endif
1358
1359     pscav(&static_roots, 1, 0);
1360     pscav(&read_only_roots, 1, 1);
1361
1362 #ifdef PRINTNOISE
1363     printf(" handlers");
1364     fflush(stdout);
1365 #endif
1366     pscav((lispobj *) all_threads->interrupt_data->interrupt_handlers,
1367           sizeof(all_threads->interrupt_data->interrupt_handlers)
1368           / sizeof(lispobj),
1369           0);
1370
1371 #ifdef PRINTNOISE
1372     printf(" stack");
1373     fflush(stdout);
1374 #endif
1375 #ifndef LISP_FEATURE_X86
1376     pscav((lispobj *)all_threads->control_stack_start,
1377           current_control_stack_pointer - 
1378           all_threads->control_stack_start,
1379           0);
1380 #else
1381 #ifdef LISP_FEATURE_GENCGC
1382     pscav_i386_stack();
1383 #endif
1384 #endif
1385
1386 #ifdef PRINTNOISE
1387     printf(" bindings");
1388     fflush(stdout);
1389 #endif
1390 #if !defined(LISP_FEATURE_X86)
1391     pscav( (lispobj *)all_threads->binding_stack_start,
1392           (lispobj *)current_binding_stack_pointer -
1393            all_threads->binding_stack_start,
1394           0);
1395 #else
1396     for_each_thread(thread) {
1397         pscav( (lispobj *)thread->binding_stack_start,
1398                (lispobj *)SymbolValue(BINDING_STACK_POINTER,thread) -
1399                (lispobj *)thread->binding_stack_start,
1400           0);
1401         pscav( (lispobj *) (thread+1),
1402                fixnum_value(SymbolValue(FREE_TLS_INDEX,0)) -
1403                (sizeof (struct thread))/(sizeof (lispobj)),
1404           0);
1405     }
1406
1407
1408 #endif
1409
1410     /* The original CMU CL code had scavenge-read-only-space code
1411      * controlled by the Lisp-level variable
1412      * *SCAVENGE-READ-ONLY-SPACE*. It was disabled by default, and it
1413      * wasn't documented under what circumstances it was useful or
1414      * safe to turn it on, so it's been turned off in SBCL. If you
1415      * want/need this functionality, and can test and document it,
1416      * please submit a patch. */
1417 #if 0
1418     if (SymbolValue(SCAVENGE_READ_ONLY_SPACE) != UNBOUND_MARKER_WIDETAG
1419         && SymbolValue(SCAVENGE_READ_ONLY_SPACE) != NIL) {
1420       unsigned  read_only_space_size =
1421           (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) -
1422           (lispobj *)READ_ONLY_SPACE_START;
1423       fprintf(stderr,
1424               "scavenging read only space: %d bytes\n",
1425               read_only_space_size * sizeof(lispobj));
1426       pscav( (lispobj *)READ_ONLY_SPACE_START, read_only_space_size, 0);
1427     }
1428 #endif
1429
1430 #ifdef PRINTNOISE
1431     printf(" static");
1432     fflush(stdout);
1433 #endif
1434     clean = (lispobj *)STATIC_SPACE_START;
1435     do {
1436         while (clean != static_free)
1437             clean = pscav(clean, static_free - clean, 0);
1438         laters = later_blocks;
1439         count = later_count;
1440         later_blocks = NULL;
1441         later_count = 0;
1442         while (laters != NULL) {
1443             for (i = 0; i < count; i++) {
1444                 if (laters->u[i].count == 0) {
1445                     ;
1446                 } else if (laters->u[i].count <= LATERMAXCOUNT) {
1447                     pscav(laters->u[i+1].ptr, laters->u[i].count, 1);
1448                     i++;
1449                 } else {
1450                     pscav(laters->u[i].ptr, 1, 1);
1451                 }
1452             }
1453             next = laters->next;
1454             free(laters);
1455             laters = next;
1456             count = LATERBLOCKSIZE;
1457         }
1458     } while (clean != static_free || later_blocks != NULL);
1459
1460 #ifdef PRINTNOISE
1461     printf(" cleanup");
1462     fflush(stdout);
1463 #endif
1464
1465     os_zero((os_vm_address_t) current_dynamic_space,
1466             (os_vm_size_t) DYNAMIC_SPACE_SIZE);
1467
1468     /* Zero the stack. Note that the stack is also zeroed by SUB-GC
1469      * calling SCRUB-CONTROL-STACK - this zeros the stack on the x86. */
1470 #ifndef LISP_FEATURE_X86
1471     os_zero((os_vm_address_t) current_control_stack_pointer,
1472             (os_vm_size_t)
1473             ((all_threads->control_stack_end -
1474               current_control_stack_pointer) * sizeof(lispobj)));
1475 #endif
1476
1477     /* It helps to update the heap free pointers so that free_heap can
1478      * verify after it's done. */
1479     SetSymbolValue(READ_ONLY_SPACE_FREE_POINTER, (lispobj)read_only_free,0);
1480     SetSymbolValue(STATIC_SPACE_FREE_POINTER, (lispobj)static_free,0);
1481
1482 #if !defined(LISP_FEATURE_X86)
1483     dynamic_space_free_pointer = current_dynamic_space;
1484     set_auto_gc_trigger(bytes_consed_between_gcs);
1485 #else
1486 #if defined LISP_FEATURE_GENCGC
1487     gc_free_heap();
1488 #else
1489 #error unsupported case /* in CMU CL, was "ibmrt using GC" */
1490 #endif
1491 #endif
1492
1493 #ifdef PRINTNOISE
1494     printf(" done]\n");
1495     fflush(stdout);
1496 #endif
1497     return 0;
1498 }