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