2 * stop and copy GC based on Cheney's algorithm
6 * This software is part of the SBCL system. See the README file for
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.
18 #include <sys/resource.h>
25 #include "interrupt.h"
30 /* So you need to debug? */
33 #define DEBUG_SPACE_PREDICATES
34 #define DEBUG_SCAVENGE_VERBOSE
35 #define DEBUG_COPY_VERBOSE
39 static lispobj *from_space;
40 static lispobj *from_space_free_pointer;
42 static lispobj *new_space;
43 static lispobj *new_space_free_pointer;
45 static int (*scavtab[256])(lispobj *where, lispobj object);
46 static lispobj (*transother[256])(lispobj object);
47 static int (*sizetab[256])(lispobj *where);
49 static struct weak_pointer *weak_pointers;
51 static void scavenge(lispobj *start, u32 nwords);
52 static void scavenge_newspace(void);
53 static void scavenge_interrupt_contexts(void);
54 static void scan_weak_pointers(void);
55 static int scav_lose(lispobj *where, lispobj object);
57 #define gc_abort() lose("GC invariant lost! File \"%s\", line %d\n", \
61 #define gc_assert(ex) do { \
62 if (!(ex)) gc_abort(); \
68 #define CEILING(x,y) (((x) + ((y) - 1)) & (~((y) - 1)))
73 #if defined(DEBUG_SPACE_PREDICATES)
76 from_space_p(lispobj object)
80 /* this can be called for untagged pointers as well as for
81 descriptors, so this assertion's not applicable
82 gc_assert(is_lisp_pointer(object));
84 ptr = (lispobj *) native_pointer(object);
86 return ((from_space <= ptr) &&
87 (ptr < from_space_free_pointer));
91 new_space_p(lispobj object)
95 gc_assert(is_lisp_pointer(object));
97 ptr = (lispobj *) native_pointer(object);
99 return ((new_space <= ptr) &&
100 (ptr < new_space_free_pointer));
105 #define from_space_p(ptr) \
106 ((from_space <= ((lispobj *) ptr)) && \
107 (((lispobj *) ptr) < from_space_free_pointer))
109 #define new_space_p(ptr) \
110 ((new_space <= ((lispobj *) ptr)) && \
111 (((lispobj *) ptr) < new_space_free_pointer))
116 /* copying objects */
119 copy_object(lispobj object, int nwords)
123 lispobj *source, *dest;
125 gc_assert(is_lisp_pointer(object));
126 gc_assert(from_space_p(object));
127 gc_assert((nwords & 0x01) == 0);
129 /* get tag of object */
130 tag = lowtag_of(object);
133 new = new_space_free_pointer;
134 new_space_free_pointer += nwords;
137 source = (lispobj *) native_pointer(object);
139 #ifdef DEBUG_COPY_VERBOSE
140 fprintf(stderr,"Copying %d words from %p to %p\n", nwords,source,new);
143 /* copy the object */
151 /* return lisp pointer of new object */
152 return (lispobj)(LOW_WORD(new) | tag);
156 /* collecting garbage */
160 tv_diff(struct timeval *x, struct timeval *y)
162 return (((double) x->tv_sec + (double) x->tv_usec * 1.0e-6) -
163 ((double) y->tv_sec + (double) y->tv_usec * 1.0e-6));
167 #define BYTES_ZERO_BEFORE_END (1<<12)
172 #define U32 unsigned long
177 U32 *ptr = (U32 *)current_control_stack_pointer;
183 } while (((unsigned long)ptr) & (BYTES_ZERO_BEFORE_END-1));
188 } while (((unsigned long)ptr) & (BYTES_ZERO_BEFORE_END-1));
195 /* Note: The generic GC interface we're implementing passes us a
196 * last_generation argument. That's meaningless for us, since we're
197 * not a generational GC. So we ignore it. */
199 collect_garbage(unsigned ignore)
202 struct timeval start_tv, stop_tv;
203 struct rusage start_rusage, stop_rusage;
204 double real_time, system_time, user_time;
205 double percent_retained, gc_rate;
206 unsigned long size_discarded;
207 unsigned long size_retained;
209 lispobj *current_static_space_free_pointer;
210 unsigned long static_space_size;
211 unsigned long control_stack_size, binding_stack_size;
215 printf("[Collecting garbage ... \n");
217 getrusage(RUSAGE_SELF, &start_rusage);
218 gettimeofday(&start_tv, (struct timezone *) 0);
222 sigaddset_blockable(&tmp);
223 sigprocmask(SIG_BLOCK, &tmp, &old);
225 current_static_space_free_pointer =
226 (lispobj *) ((unsigned long)
227 SymbolValue(STATIC_SPACE_FREE_POINTER));
230 /* Set up from space and new space pointers. */
232 from_space = current_dynamic_space;
233 from_space_free_pointer = dynamic_space_free_pointer;
236 fprintf(stderr,"from_space = %lx\n",
237 (unsigned long) current_dynamic_space);
239 if (current_dynamic_space == (lispobj *) DYNAMIC_0_SPACE_START)
240 new_space = (lispobj *)DYNAMIC_1_SPACE_START;
241 else if (current_dynamic_space == (lispobj *) DYNAMIC_1_SPACE_START)
242 new_space = (lispobj *) DYNAMIC_0_SPACE_START;
244 lose("GC lossage. Current dynamic space is bogus!\n");
246 new_space_free_pointer = new_space;
248 /* at one time we had the bright idea of using mprotect() to
249 * hide the semispace that we're not using at the moment, so
250 * we'd see immediately if anyone had a pointer to it.
251 * Unfortunately, if we gc during a call to an assembler
252 * routine with a "raw" return style, at least on PPC we are
253 * expected to return into oldspace because we can't easily
254 * update the link register - it's not tagged, and we can't do
255 * it as an offset of reg_CODE because the calling routine
256 * might be nowhere near our code vector. We hope that we
257 * don't run very far in oldspace before it catapults us into
258 * newspace by either calling something else or returning
262 os_protect(new_space,DYNAMIC_SPACE_SIZE,OS_VM_PROT_ALL);
265 /* Initialize the weak pointer list. */
266 weak_pointers = (struct weak_pointer *) NULL;
269 /* Scavenge all of the roots. */
271 printf("Scavenging interrupt contexts ...\n");
273 scavenge_interrupt_contexts();
276 printf("Scavenging interrupt handlers (%d bytes) ...\n",
277 (int)sizeof(interrupt_handlers));
279 scavenge((lispobj *) interrupt_handlers,
280 sizeof(interrupt_handlers) / sizeof(lispobj));
282 /* _size quantities are in units of sizeof(lispobj) - i.e. 4 */
284 current_control_stack_pointer-
285 (lispobj *)CONTROL_STACK_START;
287 printf("Scavenging the control stack at %p (%ld words) ...\n",
288 ((lispobj *)CONTROL_STACK_START),
291 scavenge(((lispobj *)CONTROL_STACK_START), control_stack_size);
295 current_binding_stack_pointer -
296 (lispobj *)BINDING_STACK_START;
298 printf("Scavenging the binding stack %x - %x (%d words) ...\n",
299 BINDING_STACK_START,current_binding_stack_pointer,
300 (int)(binding_stack_size));
302 scavenge(((lispobj *)BINDING_STACK_START), binding_stack_size);
305 current_static_space_free_pointer - (lispobj *) STATIC_SPACE_START;
307 printf("Scavenging static space %x - %x (%d words) ...\n",
308 STATIC_SPACE_START,current_static_space_free_pointer,
309 (int)(static_space_size));
311 scavenge(((lispobj *)STATIC_SPACE_START), static_space_size);
313 /* Scavenge newspace. */
315 printf("Scavenging new space (%d bytes) ...\n",
316 (int)((new_space_free_pointer - new_space) * sizeof(lispobj)));
321 #if defined(DEBUG_PRINT_GARBAGE)
322 print_garbage(from_space, from_space_free_pointer);
325 /* Scan the weak pointers. */
327 printf("Scanning weak pointers ...\n");
329 scan_weak_pointers();
334 printf("Flipping spaces ...\n");
337 os_zero((os_vm_address_t) current_dynamic_space,
338 (os_vm_size_t) DYNAMIC_SPACE_SIZE);
340 current_dynamic_space = new_space;
341 dynamic_space_free_pointer = new_space_free_pointer;
344 size_discarded = (from_space_free_pointer - from_space) * sizeof(lispobj);
345 size_retained = (new_space_free_pointer - new_space) * sizeof(lispobj);
350 printf("Zeroing empty part of control stack ...\n");
354 sigprocmask(SIG_SETMASK, &old, 0);
358 gettimeofday(&stop_tv, (struct timezone *) 0);
359 getrusage(RUSAGE_SELF, &stop_rusage);
363 percent_retained = (((float) size_retained) /
364 ((float) size_discarded)) * 100.0;
366 printf("Total of %ld bytes out of %ld bytes retained (%3.2f%%).\n",
367 size_retained, size_discarded, percent_retained);
369 real_time = tv_diff(&stop_tv, &start_tv);
370 user_time = tv_diff(&stop_rusage.ru_utime, &start_rusage.ru_utime);
371 system_time = tv_diff(&stop_rusage.ru_stime, &start_rusage.ru_stime);
374 printf("Statistics:\n");
375 printf("%10.2f sec of real time\n", real_time);
376 printf("%10.2f sec of user time,\n", user_time);
377 printf("%10.2f sec of system time.\n", system_time);
379 printf("Statistics: %10.2fs real, %10.2fs user, %10.2fs system.\n",
380 real_time, user_time, system_time);
383 gc_rate = ((float) size_retained / (float) (1<<20)) / real_time;
385 printf("%10.2f M bytes/sec collected.\n", gc_rate);
387 /* os_flush_icache((os_vm_address_t) 0, sizeof(unsigned long)); */
390 /* see comment above about mprotecting oldspace */
392 /* zero the from space now, to make it easier to find stale
395 /* pray that both dynamic spaces are the same size ... */
396 memset(from_space,(DYNAMIC_0_SPACE_END-DYNAMIC_0_SPACE_START-1),0);
397 os_protect(from_space,DYNAMIC_SPACE_SIZE,0); /* write-protect */
405 scavenge(lispobj *start, u32 nwords)
409 int type, words_scavenged;
412 type = widetag_of(object);
414 #if defined(DEBUG_SCAVENGE_VERBOSE)
415 fprintf(stderr,"Scavenging object at 0x%08x, object = 0x%08x, type = %d\n",
416 (unsigned long) start, (unsigned long) object, type);
419 if (is_lisp_pointer(object)) {
420 /* It be a pointer. */
421 if (from_space_p(object)) {
422 /* It currently points to old space. Check for a */
423 /* forwarding pointer. */
426 first_word = *((lispobj *)native_pointer(object));
427 if (is_lisp_pointer(first_word) &&
428 new_space_p(first_word)) {
429 /* Yep, there be a forwarding pointer. */
434 /* Scavenge that pointer. */
435 words_scavenged = (scavtab[type])(start, object);
439 /* It points somewhere other than oldspace. Leave */
444 else if (nwords==1) {
445 /* there are some situations where an
446 other-immediate may end up in a descriptor
447 register. I'm not sure whether this is
448 supposed to happen, but if it does then we
449 don't want to (a) barf or (b) scavenge over the
450 data-block, because there isn't one. So, if
451 we're checking a single word and it's anything
452 other than a pointer, just hush it up */
455 if ((scavtab[type]==scav_lose) ||
456 (((scavtab[type])(start,object))>1)) {
457 fprintf(stderr,"warning: attempted to scavenge non-descriptor value %x at %p. If you can\nreproduce this warning, send a test case to sbcl-devel@lists.sourceforge.net\n",
461 else if ((object & 3) == 0) {
462 /* It's a fixnum. Real easy. */
466 /* It's some random header object. */
467 words_scavenged = (scavtab[type])(start, object);
471 start += words_scavenged;
472 nwords -= words_scavenged;
474 gc_assert(nwords == 0);
478 scavenge_newspace(void)
480 lispobj *here, *next;
483 while (here < new_space_free_pointer) {
484 /* printf("here=%lx, new_space_free_pointer=%lx\n",
485 here,new_space_free_pointer); */
486 next = new_space_free_pointer;
487 scavenge(here, next - here);
490 /* printf("done with newspace\n"); */
493 /* scavenging interrupt contexts */
495 static int boxed_registers[] = BOXED_REGISTERS;
498 scavenge_interrupt_context(os_context_t *context)
503 unsigned long lip_offset;
504 int lip_register_pair;
506 unsigned long pc_code_offset;
507 #ifdef ARCH_HAS_LINK_REGISTER
508 unsigned long lr_code_offset;
510 #ifdef ARCH_HAS_NPC_REGISTER
511 unsigned long npc_code_offset;
513 #ifdef DEBUG_SCAVENGE_VERBOSE
514 fprintf(stderr, "Scavenging interrupt context at 0x%x\n",context);
516 /* Find the LIP's register pair and calculate its offset */
517 /* before we scavenge the context. */
519 lip = *os_context_register_addr(context, reg_LIP);
520 /* 0x7FFFFFFF or 0x7FFFFFFFFFFFFFFF ? */
521 lip_offset = 0x7FFFFFFF;
522 lip_register_pair = -1;
523 for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {
528 index = boxed_registers[i];
529 reg = *os_context_register_addr(context, index);
530 /* would be using PTR if not for integer length issues */
531 if ((reg & ~((1L<<N_LOWTAG_BITS)-1)) <= lip) {
533 if (offset < lip_offset) {
535 lip_register_pair = index;
541 /* Compute the PC's offset from the start of the CODE */
544 *os_context_pc_addr(context) -
545 *os_context_register_addr(context, reg_CODE);
546 #ifdef ARCH_HAS_NPC_REGISTER
548 *os_context_npc_addr(context) -
549 *os_context_register_addr(context, reg_CODE);
551 #ifdef ARCH_HAS_LINK_REGISTER
553 *os_context_lr_addr(context) -
554 *os_context_register_addr(context, reg_CODE);
557 /* Scavenge all boxed registers in the context. */
558 for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {
562 index = boxed_registers[i];
563 foo = *os_context_register_addr(context,index);
564 scavenge((lispobj *) &foo, 1);
565 *os_context_register_addr(context,index) = foo;
567 /* this is unlikely to work as intended on bigendian
568 * 64 bit platforms */
571 os_context_register_addr(context, index), 1);
576 *os_context_register_addr(context, reg_LIP) =
577 *os_context_register_addr(context, lip_register_pair) + lip_offset;
580 /* Fix the PC if it was in from space */
581 if (from_space_p(*os_context_pc_addr(context)))
582 *os_context_pc_addr(context) =
583 *os_context_register_addr(context, reg_CODE) + pc_code_offset;
584 #ifdef ARCH_HAS_LINK_REGISTER
585 /* Fix the LR ditto; important if we're being called from
586 * an assembly routine that expects to return using blr, otherwise
588 if (from_space_p(*os_context_lr_addr(context)))
589 *os_context_lr_addr(context) =
590 *os_context_register_addr(context, reg_CODE) + lr_code_offset;
593 #ifdef ARCH_HAS_NPC_REGISTER
594 if (from_space_p(*os_context_npc_addr(context)))
595 *os_context_npc_addr(context) =
596 *os_context_register_addr(context, reg_CODE) + npc_code_offset;
600 void scavenge_interrupt_contexts(void)
603 os_context_t *context;
605 index = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX));
607 #ifdef DEBUG_SCAVENGE_VERBOSE
608 fprintf(stderr, "%d interrupt contexts to scan\n",index);
610 for (i = 0; i < index; i++) {
611 context = lisp_interrupt_contexts[i];
612 scavenge_interrupt_context(context);
620 print_garbage(lispobj *from_space, lispobj *from_space_free_pointer)
623 int total_words_not_copied;
625 printf("Scanning from space ...\n");
627 total_words_not_copied = 0;
629 while (start < from_space_free_pointer) {
631 int forwardp, type, nwords;
635 forwardp = is_lisp_pointer(object) && new_space_p(object);
641 tag = lowtag_of(object);
644 case LIST_POINTER_LOWTAG:
647 case INSTANCE_POINTER_LOWTAG:
648 printf("Don't know about instances yet!\n");
651 case FUN_POINTER_LOWTAG:
654 case OTHER_POINTER_LOWTAG:
655 pointer = (lispobj *) native_pointer(object);
657 type = widetag_of(header);
658 nwords = (sizetab[type])(pointer);
661 type = widetag_of(object);
662 nwords = (sizetab[type])(start);
663 total_words_not_copied += nwords;
664 printf("%4d words not copied at 0x%16lx; ",
665 nwords, (unsigned long) start);
666 printf("Header word is 0x%08x\n",
667 (unsigned int) object);
671 printf("%d total words not copied.\n", total_words_not_copied);
675 /* code and code-related objects */
677 /* FIXME: Shouldn't this be defined in sbcl.h? */
678 #define FUN_RAW_ADDR_OFFSET (6*sizeof(lispobj) - FUN_POINTER_LOWTAG)
680 static lispobj trans_fun_header(lispobj object);
681 static lispobj trans_boxed(lispobj object);
684 scav_fun_pointer(lispobj *where, lispobj object)
686 lispobj *first_pointer;
691 gc_assert(is_lisp_pointer(object));
693 /* object is a pointer into from space. Not a FP */
694 first_pointer = (lispobj *) native_pointer(object);
695 first = *first_pointer;
697 /* must transport object -- object may point */
698 /* to either a function header, a closure */
699 /* function header, or to a closure header. */
701 type = widetag_of(first);
703 case SIMPLE_FUN_HEADER_WIDETAG:
704 case CLOSURE_FUN_HEADER_WIDETAG:
705 copy = trans_fun_header(object);
708 copy = trans_boxed(object);
712 first = *first_pointer = copy;
714 gc_assert(is_lisp_pointer(first));
715 gc_assert(!from_space_p(first));
722 trans_code(struct code *code)
724 struct code *new_code;
725 lispobj first, l_code, l_new_code;
726 int nheader_words, ncode_words, nwords;
727 unsigned long displacement;
728 lispobj fheaderl, *prev_pointer;
730 #if defined(DEBUG_CODE_GC)
731 printf("\nTransporting code object located at 0x%08x.\n",
732 (unsigned long) code);
735 /* if object has already been transported, just return pointer */
736 first = code->header;
737 if (is_lisp_pointer(first) && new_space_p(first)) {
739 printf("Was already transported\n");
741 return (struct code *) native_pointer(first);
744 gc_assert(widetag_of(first) == CODE_HEADER_WIDETAG);
746 /* prepare to transport the code vector */
747 l_code = (lispobj) LOW_WORD(code) | OTHER_POINTER_LOWTAG;
749 ncode_words = fixnum_value(code->code_size);
750 nheader_words = HeaderValue(code->header);
751 nwords = ncode_words + nheader_words;
752 nwords = CEILING(nwords, 2);
754 l_new_code = copy_object(l_code, nwords);
755 new_code = (struct code *) native_pointer(l_new_code);
757 displacement = l_new_code - l_code;
759 #if defined(DEBUG_CODE_GC)
760 printf("Old code object at 0x%08x, new code object at 0x%08x.\n",
761 (unsigned long) code, (unsigned long) new_code);
762 printf("Code object is %d words long.\n", nwords);
765 /* set forwarding pointer */
766 code->header = l_new_code;
768 /* set forwarding pointers for all the function headers in the */
769 /* code object. also fix all self pointers */
771 fheaderl = code->entry_points;
772 prev_pointer = &new_code->entry_points;
774 while (fheaderl != NIL) {
775 struct simple_fun *fheaderp, *nfheaderp;
778 fheaderp = (struct simple_fun *) native_pointer(fheaderl);
779 gc_assert(widetag_of(fheaderp->header) == SIMPLE_FUN_HEADER_WIDETAG);
781 /* Calculate the new function pointer and the new */
782 /* function header. */
783 nfheaderl = fheaderl + displacement;
784 nfheaderp = (struct simple_fun *) native_pointer(nfheaderl);
786 /* set forwarding pointer */
788 printf("fheaderp->header (at %x) <- %x\n",
789 &(fheaderp->header) , nfheaderl);
791 fheaderp->header = nfheaderl;
793 /* fix self pointer */
794 nfheaderp->self = nfheaderl;
796 *prev_pointer = nfheaderl;
798 fheaderl = fheaderp->next;
799 prev_pointer = &nfheaderp->next;
803 os_flush_icache((os_vm_address_t) (((int *)new_code) + nheader_words),
804 ncode_words * sizeof(int));
810 scav_code_header(lispobj *where, lispobj object)
813 int nheader_words, ncode_words, nwords;
815 struct simple_fun *fheaderp;
817 code = (struct code *) where;
818 ncode_words = fixnum_value(code->code_size);
819 nheader_words = HeaderValue(object);
820 nwords = ncode_words + nheader_words;
821 nwords = CEILING(nwords, 2);
823 #if defined(DEBUG_CODE_GC)
824 printf("\nScavening code object at 0x%08x.\n",
825 (unsigned long) where);
826 printf("Code object is %d words long.\n", nwords);
827 printf("Scavenging boxed section of code data block (%d words).\n",
831 /* Scavenge the boxed section of the code data block */
832 scavenge(where + 1, nheader_words - 1);
834 /* Scavenge the boxed section of each function object in the */
835 /* code data block */
836 fheaderl = code->entry_points;
837 while (fheaderl != NIL) {
838 fheaderp = (struct simple_fun *) native_pointer(fheaderl);
839 gc_assert(widetag_of(fheaderp->header) == SIMPLE_FUN_HEADER_WIDETAG);
841 #if defined(DEBUG_CODE_GC)
842 printf("Scavenging boxed section of entry point located at 0x%08x.\n",
843 (unsigned long) native_pointer(fheaderl));
845 scavenge(&fheaderp->name, 1);
846 scavenge(&fheaderp->arglist, 1);
847 scavenge(&fheaderp->type, 1);
849 fheaderl = fheaderp->next;
856 trans_code_header(lispobj object)
860 ncode = trans_code((struct code *) native_pointer(object));
861 return (lispobj) LOW_WORD(ncode) | OTHER_POINTER_LOWTAG;
865 size_code_header(lispobj *where)
868 int nheader_words, ncode_words, nwords;
870 code = (struct code *) where;
872 ncode_words = fixnum_value(code->code_size);
873 nheader_words = HeaderValue(code->header);
874 nwords = ncode_words + nheader_words;
875 nwords = CEILING(nwords, 2);
882 scav_return_pc_header(lispobj *where, lispobj object)
884 fprintf(stderr, "GC lossage. Should not be scavenging a ");
885 fprintf(stderr, "Return PC Header.\n");
886 fprintf(stderr, "where = 0x%p, object = 0x%x", where, object);
892 trans_return_pc_header(lispobj object)
894 struct simple_fun *return_pc;
895 unsigned long offset;
896 struct code *code, *ncode;
898 return_pc = (struct simple_fun *) native_pointer(object);
899 offset = HeaderValue(return_pc->header) * 4 ;
901 /* Transport the whole code object */
902 code = (struct code *) ((unsigned long) return_pc - offset);
904 printf("trans_return_pc_header object=%x, code=%lx\n",object,code);
906 ncode = trans_code(code);
907 if (object==0x304748d7) {
908 /* monitor_or_something(); */
910 ret= ((lispobj) LOW_WORD(ncode) + offset) | OTHER_POINTER_LOWTAG;
912 printf("trans_return_pc_header returning %x\n",ret);
917 /* On the 386, closures hold a pointer to the raw address instead of
918 * the function object, so we can use CALL [$FDEFN+const] to invoke
919 * the function without loading it into a register. Given that code
920 * objects don't move, we don't need to update anything, but we do
921 * have to figure out that the function is still live. */
924 scav_closure_header(where, object)
925 lispobj *where, object;
927 struct closure *closure;
930 closure = (struct closure *)where;
931 fun = closure->fun - FUN_RAW_ADDR_OFFSET;
939 scav_fun_header(lispobj *where, lispobj object)
941 fprintf(stderr, "GC lossage. Should not be scavenging a ");
942 fprintf(stderr, "Function Header.\n");
943 fprintf(stderr, "where = 0x%p, object = 0x%08x",
944 where, (unsigned int) object);
950 trans_fun_header(lispobj object)
952 struct simple_fun *fheader;
953 unsigned long offset;
954 struct code *code, *ncode;
956 fheader = (struct simple_fun *) native_pointer(object);
957 offset = HeaderValue(fheader->header) * 4;
959 /* Transport the whole code object */
960 code = (struct code *) ((unsigned long) fheader - offset);
961 ncode = trans_code(code);
963 return ((lispobj) LOW_WORD(ncode) + offset) | FUN_POINTER_LOWTAG;
971 scav_instance_pointer(lispobj *where, lispobj object)
973 lispobj *first_pointer;
975 /* object is a pointer into from space. Not a FP */
976 first_pointer = (lispobj *) native_pointer(object);
978 *where = *first_pointer = trans_boxed(object);
983 /* lists and conses */
985 static lispobj trans_list(lispobj object);
988 scav_list_pointer(lispobj *where, lispobj object)
990 lispobj first, *first_pointer;
992 gc_assert(is_lisp_pointer(object));
994 /* object is a pointer into from space. Not a FP. */
995 first_pointer = (lispobj *) native_pointer(object);
997 first = *first_pointer = trans_list(object);
999 gc_assert(is_lisp_pointer(first));
1000 gc_assert(!from_space_p(first));
1007 trans_list(lispobj object)
1009 lispobj new_list_pointer;
1010 struct cons *cons, *new_cons;
1012 cons = (struct cons *) native_pointer(object);
1014 /* ### Don't use copy_object here. */
1015 new_list_pointer = copy_object(object, 2);
1016 new_cons = (struct cons *) native_pointer(new_list_pointer);
1018 /* Set forwarding pointer. */
1019 cons->car = new_list_pointer;
1021 /* Try to linearize the list in the cdr direction to help reduce */
1025 lispobj cdr, new_cdr, first;
1026 struct cons *cdr_cons, *new_cdr_cons;
1030 if (lowtag_of(cdr) != LIST_POINTER_LOWTAG ||
1031 !from_space_p(cdr) ||
1032 (is_lisp_pointer(first = *(lispobj *)native_pointer(cdr))
1033 && new_space_p(first)))
1036 cdr_cons = (struct cons *) native_pointer(cdr);
1038 /* ### Don't use copy_object here */
1039 new_cdr = copy_object(cdr, 2);
1040 new_cdr_cons = (struct cons *) native_pointer(new_cdr);
1042 /* Set forwarding pointer */
1043 cdr_cons->car = new_cdr;
1045 /* Update the cdr of the last cons copied into new */
1046 /* space to keep the newspace scavenge from having to */
1048 new_cons->cdr = new_cdr;
1051 new_cons = new_cdr_cons;
1054 return new_list_pointer;
1058 /* scavenging and transporting other pointers */
1061 scav_other_pointer(lispobj *where, lispobj object)
1063 lispobj first, *first_pointer;
1065 gc_assert(is_lisp_pointer(object));
1067 /* Object is a pointer into from space - not a FP */
1068 first_pointer = (lispobj *) native_pointer(object);
1069 first = *first_pointer = (transother[widetag_of(*first_pointer)])(object);
1071 gc_assert(is_lisp_pointer(first));
1072 gc_assert(!from_space_p(first));
1079 /* immediate, boxed, and unboxed objects */
1082 size_pointer(lispobj *where)
1088 scav_immediate(lispobj *where, lispobj object)
1094 trans_immediate(lispobj object)
1096 fprintf(stderr, "GC lossage. Trying to transport an immediate!?\n");
1102 size_immediate(lispobj *where)
1109 scav_boxed(lispobj *where, lispobj object)
1115 trans_boxed(lispobj object)
1118 unsigned long length;
1120 gc_assert(is_lisp_pointer(object));
1122 header = *((lispobj *) native_pointer(object));
1123 length = HeaderValue(header) + 1;
1124 length = CEILING(length, 2);
1126 return copy_object(object, length);
1130 size_boxed(lispobj *where)
1133 unsigned long length;
1136 length = HeaderValue(header) + 1;
1137 length = CEILING(length, 2);
1142 /* Note: on the sparc we don't have to do anything special for fdefns, */
1143 /* 'cause the raw-addr has a function lowtag. */
1146 scav_fdefn(lispobj *where, lispobj object)
1148 struct fdefn *fdefn;
1150 fdefn = (struct fdefn *)where;
1152 if ((char *)(fdefn->fun + FUN_RAW_ADDR_OFFSET)
1153 == (char *)((unsigned long)(fdefn->raw_addr))) {
1154 scavenge(where + 1, sizeof(struct fdefn)/sizeof(lispobj) - 1);
1156 (u32) ((char *) LOW_WORD(fdefn->fun)) + FUN_RAW_ADDR_OFFSET;
1157 return sizeof(struct fdefn) / sizeof(lispobj);
1165 scav_unboxed(lispobj *where, lispobj object)
1167 unsigned long length;
1169 length = HeaderValue(object) + 1;
1170 length = CEILING(length, 2);
1176 trans_unboxed(lispobj object)
1179 unsigned long length;
1182 gc_assert(is_lisp_pointer(object));
1184 header = *((lispobj *) native_pointer(object));
1185 length = HeaderValue(header) + 1;
1186 length = CEILING(length, 2);
1188 return copy_object(object, length);
1192 size_unboxed(lispobj *where)
1195 unsigned long length;
1198 length = HeaderValue(header) + 1;
1199 length = CEILING(length, 2);
1205 /* vector-like objects */
1207 #define NWORDS(x,y) (CEILING((x),(y)) / (y))
1210 scav_string(lispobj *where, lispobj object)
1212 struct vector *vector;
1215 /* NOTE: Strings contain one more byte of data than the length */
1216 /* slot indicates. */
1218 vector = (struct vector *) where;
1219 length = fixnum_value(vector->length) + 1;
1220 nwords = CEILING(NWORDS(length, 4) + 2, 2);
1226 trans_string(lispobj object)
1228 struct vector *vector;
1231 gc_assert(is_lisp_pointer(object));
1233 /* NOTE: Strings contain one more byte of data than the length */
1234 /* slot indicates. */
1236 vector = (struct vector *) native_pointer(object);
1237 length = fixnum_value(vector->length) + 1;
1238 nwords = CEILING(NWORDS(length, 4) + 2, 2);
1240 return copy_object(object, nwords);
1244 size_string(lispobj *where)
1246 struct vector *vector;
1249 /* NOTE: Strings contain one more byte of data than the length */
1250 /* slot indicates. */
1252 vector = (struct vector *) where;
1253 length = fixnum_value(vector->length) + 1;
1254 nwords = CEILING(NWORDS(length, 4) + 2, 2);
1260 scav_vector(lispobj *where, lispobj object)
1262 if (HeaderValue(object) == subtype_VectorValidHashing) {
1264 (subtype_VectorMustRehash<<N_WIDETAG_BITS) | SIMPLE_VECTOR_WIDETAG;
1272 trans_vector(lispobj object)
1274 struct vector *vector;
1277 gc_assert(is_lisp_pointer(object));
1279 vector = (struct vector *) native_pointer(object);
1281 length = fixnum_value(vector->length);
1282 nwords = CEILING(length + 2, 2);
1284 return copy_object(object, nwords);
1288 size_vector(lispobj *where)
1290 struct vector *vector;
1293 vector = (struct vector *) where;
1294 length = fixnum_value(vector->length);
1295 nwords = CEILING(length + 2, 2);
1302 scav_vector_bit(lispobj *where, lispobj object)
1304 struct vector *vector;
1307 vector = (struct vector *) where;
1308 length = fixnum_value(vector->length);
1309 nwords = CEILING(NWORDS(length, 32) + 2, 2);
1315 trans_vector_bit(lispobj object)
1317 struct vector *vector;
1320 gc_assert(is_lisp_pointer(object));
1322 vector = (struct vector *) native_pointer(object);
1323 length = fixnum_value(vector->length);
1324 nwords = CEILING(NWORDS(length, 32) + 2, 2);
1326 return copy_object(object, nwords);
1330 size_vector_bit(lispobj *where)
1332 struct vector *vector;
1335 vector = (struct vector *) where;
1336 length = fixnum_value(vector->length);
1337 nwords = CEILING(NWORDS(length, 32) + 2, 2);
1344 scav_vector_unsigned_byte_2(lispobj *where, lispobj object)
1346 struct vector *vector;
1349 vector = (struct vector *) where;
1350 length = fixnum_value(vector->length);
1351 nwords = CEILING(NWORDS(length, 16) + 2, 2);
1357 trans_vector_unsigned_byte_2(lispobj object)
1359 struct vector *vector;
1362 gc_assert(is_lisp_pointer(object));
1364 vector = (struct vector *) native_pointer(object);
1365 length = fixnum_value(vector->length);
1366 nwords = CEILING(NWORDS(length, 16) + 2, 2);
1368 return copy_object(object, nwords);
1372 size_vector_unsigned_byte_2(lispobj *where)
1374 struct vector *vector;
1377 vector = (struct vector *) where;
1378 length = fixnum_value(vector->length);
1379 nwords = CEILING(NWORDS(length, 16) + 2, 2);
1386 scav_vector_unsigned_byte_4(lispobj *where, lispobj object)
1388 struct vector *vector;
1391 vector = (struct vector *) where;
1392 length = fixnum_value(vector->length);
1393 nwords = CEILING(NWORDS(length, 8) + 2, 2);
1399 trans_vector_unsigned_byte_4(lispobj object)
1401 struct vector *vector;
1404 gc_assert(is_lisp_pointer(object));
1406 vector = (struct vector *) native_pointer(object);
1407 length = fixnum_value(vector->length);
1408 nwords = CEILING(NWORDS(length, 8) + 2, 2);
1410 return copy_object(object, nwords);
1414 size_vector_unsigned_byte_4(lispobj *where)
1416 struct vector *vector;
1419 vector = (struct vector *) where;
1420 length = fixnum_value(vector->length);
1421 nwords = CEILING(NWORDS(length, 8) + 2, 2);
1428 scav_vector_unsigned_byte_8(lispobj *where, lispobj object)
1430 struct vector *vector;
1433 vector = (struct vector *) where;
1434 length = fixnum_value(vector->length);
1435 nwords = CEILING(NWORDS(length, 4) + 2, 2);
1441 trans_vector_unsigned_byte_8(lispobj object)
1443 struct vector *vector;
1446 gc_assert(is_lisp_pointer(object));
1448 vector = (struct vector *) native_pointer(object);
1449 length = fixnum_value(vector->length);
1450 nwords = CEILING(NWORDS(length, 4) + 2, 2);
1452 return copy_object(object, nwords);
1456 size_vector_unsigned_byte_8(lispobj *where)
1458 struct vector *vector;
1461 vector = (struct vector *) where;
1462 length = fixnum_value(vector->length);
1463 nwords = CEILING(NWORDS(length, 4) + 2, 2);
1470 scav_vector_unsigned_byte_16(lispobj *where, lispobj object)
1472 struct vector *vector;
1475 vector = (struct vector *) where;
1476 length = fixnum_value(vector->length);
1477 nwords = CEILING(NWORDS(length, 2) + 2, 2);
1483 trans_vector_unsigned_byte_16(lispobj object)
1485 struct vector *vector;
1488 gc_assert(is_lisp_pointer(object));
1490 vector = (struct vector *) native_pointer(object);
1491 length = fixnum_value(vector->length);
1492 nwords = CEILING(NWORDS(length, 2) + 2, 2);
1494 return copy_object(object, nwords);
1498 size_vector_unsigned_byte_16(lispobj *where)
1500 struct vector *vector;
1503 vector = (struct vector *) where;
1504 length = fixnum_value(vector->length);
1505 nwords = CEILING(NWORDS(length, 2) + 2, 2);
1512 scav_vector_unsigned_byte_32(lispobj *where, lispobj object)
1514 struct vector *vector;
1517 vector = (struct vector *) where;
1518 length = fixnum_value(vector->length);
1519 nwords = CEILING(length + 2, 2);
1525 trans_vector_unsigned_byte_32(lispobj object)
1527 struct vector *vector;
1530 gc_assert(is_lisp_pointer(object));
1532 vector = (struct vector *) native_pointer(object);
1533 length = fixnum_value(vector->length);
1534 nwords = CEILING(length + 2, 2);
1536 return copy_object(object, nwords);
1540 size_vector_unsigned_byte_32(lispobj *where)
1542 struct vector *vector;
1545 vector = (struct vector *) where;
1546 length = fixnum_value(vector->length);
1547 nwords = CEILING(length + 2, 2);
1553 scav_vector_single_float(lispobj *where, lispobj object)
1555 struct vector *vector;
1558 vector = (struct vector *) where;
1559 length = fixnum_value(vector->length);
1560 nwords = CEILING(length + 2, 2);
1566 trans_vector_single_float(lispobj object)
1568 struct vector *vector;
1571 gc_assert(is_lisp_pointer(object));
1573 vector = (struct vector *) native_pointer(object);
1574 length = fixnum_value(vector->length);
1575 nwords = CEILING(length + 2, 2);
1577 return copy_object(object, nwords);
1581 size_vector_single_float(lispobj *where)
1583 struct vector *vector;
1586 vector = (struct vector *) where;
1587 length = fixnum_value(vector->length);
1588 nwords = CEILING(length + 2, 2);
1595 scav_vector_double_float(lispobj *where, lispobj object)
1597 struct vector *vector;
1600 vector = (struct vector *) where;
1601 length = fixnum_value(vector->length);
1602 nwords = CEILING(length * 2 + 2, 2);
1608 trans_vector_double_float(lispobj object)
1610 struct vector *vector;
1613 gc_assert(is_lisp_pointer(object));
1615 vector = (struct vector *) native_pointer(object);
1616 length = fixnum_value(vector->length);
1617 nwords = CEILING(length * 2 + 2, 2);
1619 return copy_object(object, nwords);
1623 size_vector_double_float(lispobj *where)
1625 struct vector *vector;
1628 vector = (struct vector *) where;
1629 length = fixnum_value(vector->length);
1630 nwords = CEILING(length * 2 + 2, 2);
1636 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
1638 scav_vector_long_float(lispobj *where, lispobj object)
1640 struct vector *vector;
1643 vector = (struct vector *) where;
1644 length = fixnum_value(vector->length);
1646 nwords = CEILING(length * 4 + 2, 2);
1653 trans_vector_long_float(lispobj object)
1655 struct vector *vector;
1658 gc_assert(is_lisp_pointer(object));
1660 vector = (struct vector *) native_pointer(object);
1661 length = fixnum_value(vector->length);
1663 nwords = CEILING(length * 4 + 2, 2);
1666 return copy_object(object, nwords);
1670 size_vector_long_float(lispobj *where)
1672 struct vector *vector;
1675 vector = (struct vector *) where;
1676 length = fixnum_value(vector->length);
1678 nwords = CEILING(length * 4 + 2, 2);
1686 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
1688 scav_vector_complex_single_float(lispobj *where, lispobj object)
1690 struct vector *vector;
1693 vector = (struct vector *) where;
1694 length = fixnum_value(vector->length);
1695 nwords = CEILING(length * 2 + 2, 2);
1701 trans_vector_complex_single_float(lispobj object)
1703 struct vector *vector;
1706 gc_assert(is_lisp_pointer(object));
1708 vector = (struct vector *) native_pointer(object);
1709 length = fixnum_value(vector->length);
1710 nwords = CEILING(length * 2 + 2, 2);
1712 return copy_object(object, nwords);
1716 size_vector_complex_single_float(lispobj *where)
1718 struct vector *vector;
1721 vector = (struct vector *) where;
1722 length = fixnum_value(vector->length);
1723 nwords = CEILING(length * 2 + 2, 2);
1729 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
1731 scav_vector_complex_double_float(lispobj *where, lispobj object)
1733 struct vector *vector;
1736 vector = (struct vector *) where;
1737 length = fixnum_value(vector->length);
1738 nwords = CEILING(length * 4 + 2, 2);
1744 trans_vector_complex_double_float(lispobj object)
1746 struct vector *vector;
1749 gc_assert(is_lisp_pointer(object));
1751 vector = (struct vector *) native_pointer(object);
1752 length = fixnum_value(vector->length);
1753 nwords = CEILING(length * 4 + 2, 2);
1755 return copy_object(object, nwords);
1759 size_vector_complex_double_float(lispobj *where)
1761 struct vector *vector;
1764 vector = (struct vector *) where;
1765 length = fixnum_value(vector->length);
1766 nwords = CEILING(length * 4 + 2, 2);
1772 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
1774 scav_vector_complex_long_float(lispobj *where, lispobj object)
1776 struct vector *vector;
1779 vector = (struct vector *) where;
1780 length = fixnum_value(vector->length);
1782 nwords = CEILING(length * 8 + 2, 2);
1789 trans_vector_complex_long_float(lispobj object)
1791 struct vector *vector;
1794 gc_assert(is_lisp_pointer(object));
1796 vector = (struct vector *) native_pointer(object);
1797 length = fixnum_value(vector->length);
1799 nwords = CEILING(length * 8 + 2, 2);
1802 return copy_object(object, nwords);
1806 size_vector_complex_long_float(lispobj *where)
1808 struct vector *vector;
1811 vector = (struct vector *) where;
1812 length = fixnum_value(vector->length);
1814 nwords = CEILING(length * 8 + 2, 2);
1824 #define WEAK_POINTER_NWORDS \
1825 CEILING((sizeof(struct weak_pointer) / sizeof(lispobj)), 2)
1828 scav_weak_pointer(lispobj *where, lispobj object)
1830 /* Do not let GC scavenge the value slot of the weak pointer */
1831 /* (that is why it is a weak pointer). Note: we could use */
1832 /* the scav_unboxed method here. */
1834 return WEAK_POINTER_NWORDS;
1838 trans_weak_pointer(lispobj object)
1841 struct weak_pointer *wp;
1843 gc_assert(is_lisp_pointer(object));
1845 #if defined(DEBUG_WEAK)
1846 printf("Transporting weak pointer from 0x%08x\n", object);
1849 /* Need to remember where all the weak pointers are that have */
1850 /* been transported so they can be fixed up in a post-GC pass. */
1852 copy = copy_object(object, WEAK_POINTER_NWORDS);
1853 wp = (struct weak_pointer *) native_pointer(copy);
1856 /* Push the weak pointer onto the list of weak pointers. */
1857 wp->next = LOW_WORD(weak_pointers);
1864 size_weak_pointer(lispobj *where)
1866 return WEAK_POINTER_NWORDS;
1869 void scan_weak_pointers(void)
1871 struct weak_pointer *wp;
1873 for (wp = weak_pointers; wp != (struct weak_pointer *) NULL;
1874 wp = (struct weak_pointer *)((unsigned long)wp->next)) {
1876 lispobj first, *first_pointer;
1880 #if defined(DEBUG_WEAK)
1881 printf("Weak pointer at 0x%p\n", wp);
1882 printf("Value: 0x%08x\n", (unsigned int) value);
1885 if (!(is_lisp_pointer(value) && from_space_p(value)))
1888 /* Now, we need to check if the object has been */
1889 /* forwarded. If it has been, the weak pointer is */
1890 /* still good and needs to be updated. Otherwise, the */
1891 /* weak pointer needs to be nil'ed out. */
1893 first_pointer = (lispobj *) native_pointer(value);
1894 first = *first_pointer;
1896 #if defined(DEBUG_WEAK)
1897 printf("First: 0x%08x\n", (unsigned long) first);
1900 if (is_lisp_pointer(first) && new_space_p(first))
1911 /* initialization */
1914 scav_lose(lispobj *where, lispobj object)
1916 fprintf(stderr, "GC lossage. No scavenge function for object 0x%08x (at 0x%016lx)\n",
1917 (unsigned int) object, (unsigned long)where);
1923 trans_lose(lispobj object)
1925 fprintf(stderr, "GC lossage. No transport function for object 0x%08x\n",
1926 (unsigned int)object);
1932 size_lose(lispobj *where)
1934 fprintf(stderr, "Size lossage. No size function for object at 0x%p\n",
1936 fprintf(stderr, "First word of object: 0x%08x\n",
1941 /* KLUDGE: SBCL already has two GC implementations, and if someday the
1942 * precise generational GC is revived, it might have three. It would
1943 * be nice to share the scavtab[] data set up here, and perhaps other
1944 * things too, between all of them, rather than trying to maintain
1945 * multiple copies. -- WHN 2001-05-09 */
1951 /* scavenge table */
1952 for (i = 0; i < 256; i++)
1953 scavtab[i] = scav_lose;
1954 /* scavtab[i] = scav_immediate; */
1956 for (i = 0; i < 32; i++) {
1957 scavtab[EVEN_FIXNUM_LOWTAG|(i<<3)] = scav_immediate;
1958 scavtab[FUN_POINTER_LOWTAG|(i<<3)] = scav_fun_pointer;
1959 /* skipping OTHER_IMMEDIATE_0_LOWTAG */
1960 scavtab[LIST_POINTER_LOWTAG|(i<<3)] = scav_list_pointer;
1961 scavtab[ODD_FIXNUM_LOWTAG|(i<<3)] = scav_immediate;
1962 scavtab[INSTANCE_POINTER_LOWTAG|(i<<3)] =scav_instance_pointer;
1963 /* skipping OTHER_IMMEDIATE_1_LOWTAG */
1964 scavtab[OTHER_POINTER_LOWTAG|(i<<3)] = scav_other_pointer;
1967 scavtab[BIGNUM_WIDETAG] = scav_unboxed;
1968 scavtab[RATIO_WIDETAG] = scav_boxed;
1969 scavtab[SINGLE_FLOAT_WIDETAG] = scav_unboxed;
1970 scavtab[DOUBLE_FLOAT_WIDETAG] = scav_unboxed;
1971 #ifdef LONG_FLOAT_WIDETAG
1972 scavtab[LONG_FLOAT_WIDETAG] = scav_unboxed;
1974 scavtab[COMPLEX_WIDETAG] = scav_boxed;
1975 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
1976 scavtab[COMPLEX_SINGLE_FLOAT_WIDETAG] = scav_unboxed;
1978 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
1979 scavtab[COMPLEX_DOUBLE_FLOAT_WIDETAG] = scav_unboxed;
1981 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
1982 scavtab[COMPLEX_LONG_FLOAT_WIDETAG] = scav_unboxed;
1984 scavtab[SIMPLE_ARRAY_WIDETAG] = scav_boxed;
1985 scavtab[SIMPLE_STRING_WIDETAG] = scav_string;
1986 scavtab[SIMPLE_BIT_VECTOR_WIDETAG] = scav_vector_bit;
1987 scavtab[SIMPLE_VECTOR_WIDETAG] = scav_vector;
1988 scavtab[SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG] =
1989 scav_vector_unsigned_byte_2;
1990 scavtab[SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG] =
1991 scav_vector_unsigned_byte_4;
1992 scavtab[SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG] =
1993 scav_vector_unsigned_byte_8;
1994 scavtab[SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG] =
1995 scav_vector_unsigned_byte_16;
1996 scavtab[SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG] =
1997 scav_vector_unsigned_byte_32;
1998 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
1999 scavtab[SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG] =
2000 scav_vector_unsigned_byte_8;
2002 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
2003 scavtab[SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG] =
2004 scav_vector_unsigned_byte_16;
2006 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
2007 scavtab[SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG] =
2008 scav_vector_unsigned_byte_32;
2010 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
2011 scavtab[SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG] =
2012 scav_vector_unsigned_byte_32;
2014 scavtab[SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG] = scav_vector_single_float;
2015 scavtab[SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG] = scav_vector_double_float;
2016 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
2017 scavtab[SIMPLE_ARRAY_LONG_FLOAT_WIDETAG] = scav_vector_long_float;
2019 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
2020 scavtab[SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG] =
2021 scav_vector_complex_single_float;
2023 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
2024 scavtab[SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG] =
2025 scav_vector_complex_double_float;
2027 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
2028 scavtab[SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG] =
2029 scav_vector_complex_long_float;
2031 scavtab[COMPLEX_STRING_WIDETAG] = scav_boxed;
2032 scavtab[COMPLEX_BIT_VECTOR_WIDETAG] = scav_boxed;
2033 scavtab[COMPLEX_VECTOR_WIDETAG] = scav_boxed;
2034 scavtab[COMPLEX_ARRAY_WIDETAG] = scav_boxed;
2035 scavtab[CODE_HEADER_WIDETAG] = scav_code_header;
2036 scavtab[SIMPLE_FUN_HEADER_WIDETAG] = scav_fun_header;
2037 scavtab[CLOSURE_FUN_HEADER_WIDETAG] = scav_fun_header;
2038 scavtab[RETURN_PC_HEADER_WIDETAG] = scav_return_pc_header;
2040 scavtab[CLOSURE_HEADER_WIDETAG] = scav_closure_header;
2041 scavtab[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = scav_closure_header;
2043 scavtab[CLOSURE_HEADER_WIDETAG] = scav_boxed;
2044 scavtab[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = scav_boxed;
2046 scavtab[VALUE_CELL_HEADER_WIDETAG] = scav_boxed;
2047 scavtab[SYMBOL_HEADER_WIDETAG] = scav_boxed;
2048 scavtab[BASE_CHAR_WIDETAG] = scav_immediate;
2049 scavtab[SAP_WIDETAG] = scav_unboxed;
2050 scavtab[UNBOUND_MARKER_WIDETAG] = scav_immediate;
2051 scavtab[WEAK_POINTER_WIDETAG] = scav_weak_pointer;
2052 scavtab[INSTANCE_HEADER_WIDETAG] = scav_boxed;
2054 scavtab[FDEFN_WIDETAG] = scav_fdefn;
2056 scavtab[FDEFN_WIDETAG] = scav_boxed;
2059 /* Transport Other Table */
2060 for (i = 0; i < 256; i++)
2061 transother[i] = trans_lose;
2063 transother[BIGNUM_WIDETAG] = trans_unboxed;
2064 transother[RATIO_WIDETAG] = trans_boxed;
2065 transother[SINGLE_FLOAT_WIDETAG] = trans_unboxed;
2066 transother[DOUBLE_FLOAT_WIDETAG] = trans_unboxed;
2067 #ifdef LONG_FLOAT_WIDETAG
2068 transother[LONG_FLOAT_WIDETAG] = trans_unboxed;
2070 transother[COMPLEX_WIDETAG] = trans_boxed;
2071 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
2072 transother[COMPLEX_SINGLE_FLOAT_WIDETAG] = trans_unboxed;
2074 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
2075 transother[COMPLEX_DOUBLE_FLOAT_WIDETAG] = trans_unboxed;
2077 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
2078 transother[COMPLEX_LONG_FLOAT_WIDETAG] = trans_unboxed;
2080 transother[SIMPLE_ARRAY_WIDETAG] = trans_boxed;
2081 transother[SIMPLE_STRING_WIDETAG] = trans_string;
2082 transother[SIMPLE_BIT_VECTOR_WIDETAG] = trans_vector_bit;
2083 transother[SIMPLE_VECTOR_WIDETAG] = trans_vector;
2084 transother[SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG] =
2085 trans_vector_unsigned_byte_2;
2086 transother[SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG] =
2087 trans_vector_unsigned_byte_4;
2088 transother[SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG] =
2089 trans_vector_unsigned_byte_8;
2090 transother[SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG] =
2091 trans_vector_unsigned_byte_16;
2092 transother[SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG] =
2093 trans_vector_unsigned_byte_32;
2094 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
2095 transother[SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG] =
2096 trans_vector_unsigned_byte_8;
2098 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
2099 transother[SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG] =
2100 trans_vector_unsigned_byte_16;
2102 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
2103 transother[SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG] =
2104 trans_vector_unsigned_byte_32;
2106 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
2107 transother[SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG] =
2108 trans_vector_unsigned_byte_32;
2110 transother[SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG] =
2111 trans_vector_single_float;
2112 transother[SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG] =
2113 trans_vector_double_float;
2114 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
2115 transother[SIMPLE_ARRAY_LONG_FLOAT_WIDETAG] =
2116 trans_vector_long_float;
2118 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
2119 transother[SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG] =
2120 trans_vector_complex_single_float;
2122 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
2123 transother[SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG] =
2124 trans_vector_complex_double_float;
2126 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
2127 transother[SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG] =
2128 trans_vector_complex_long_float;
2130 transother[COMPLEX_STRING_WIDETAG] = trans_boxed;
2131 transother[COMPLEX_BIT_VECTOR_WIDETAG] = trans_boxed;
2132 transother[COMPLEX_VECTOR_WIDETAG] = trans_boxed;
2133 transother[COMPLEX_ARRAY_WIDETAG] = trans_boxed;
2134 transother[CODE_HEADER_WIDETAG] = trans_code_header;
2135 transother[SIMPLE_FUN_HEADER_WIDETAG] = trans_fun_header;
2136 transother[CLOSURE_FUN_HEADER_WIDETAG] = trans_fun_header;
2137 transother[RETURN_PC_HEADER_WIDETAG] = trans_return_pc_header;
2138 transother[CLOSURE_HEADER_WIDETAG] = trans_boxed;
2139 transother[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = trans_boxed;
2140 transother[VALUE_CELL_HEADER_WIDETAG] = trans_boxed;
2141 transother[SYMBOL_HEADER_WIDETAG] = trans_boxed;
2142 transother[BASE_CHAR_WIDETAG] = trans_immediate;
2143 transother[SAP_WIDETAG] = trans_unboxed;
2144 transother[UNBOUND_MARKER_WIDETAG] = trans_immediate;
2145 transother[WEAK_POINTER_WIDETAG] = trans_weak_pointer;
2146 transother[INSTANCE_HEADER_WIDETAG] = trans_boxed;
2147 transother[FDEFN_WIDETAG] = trans_boxed;
2151 for (i = 0; i < 256; i++)
2152 sizetab[i] = size_lose;
2154 for (i = 0; i < 32; i++) {
2155 sizetab[EVEN_FIXNUM_LOWTAG|(i<<3)] = size_immediate;
2156 sizetab[FUN_POINTER_LOWTAG|(i<<3)] = size_pointer;
2157 /* skipping OTHER_IMMEDIATE_0_LOWTAG */
2158 sizetab[LIST_POINTER_LOWTAG|(i<<3)] = size_pointer;
2159 sizetab[ODD_FIXNUM_LOWTAG|(i<<3)] = size_immediate;
2160 sizetab[INSTANCE_POINTER_LOWTAG|(i<<3)] = size_pointer;
2161 /* skipping OTHER_IMMEDIATE_1_LOWTAG */
2162 sizetab[OTHER_POINTER_LOWTAG|(i<<3)] = size_pointer;
2165 sizetab[BIGNUM_WIDETAG] = size_unboxed;
2166 sizetab[RATIO_WIDETAG] = size_boxed;
2167 sizetab[SINGLE_FLOAT_WIDETAG] = size_unboxed;
2168 sizetab[DOUBLE_FLOAT_WIDETAG] = size_unboxed;
2169 #ifdef LONG_FLOAT_WIDETAG
2170 sizetab[LONG_FLOAT_WIDETAG] = size_unboxed;
2172 sizetab[COMPLEX_WIDETAG] = size_boxed;
2173 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
2174 sizetab[COMPLEX_SINGLE_FLOAT_WIDETAG] = size_unboxed;
2176 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
2177 sizetab[COMPLEX_DOUBLE_FLOAT_WIDETAG] = size_unboxed;
2179 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
2180 sizetab[COMPLEX_LONG_FLOAT_WIDETAG] = size_unboxed;
2182 sizetab[SIMPLE_ARRAY_WIDETAG] = size_boxed;
2183 sizetab[SIMPLE_STRING_WIDETAG] = size_string;
2184 sizetab[SIMPLE_BIT_VECTOR_WIDETAG] = size_vector_bit;
2185 sizetab[SIMPLE_VECTOR_WIDETAG] = size_vector;
2186 sizetab[SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG] =
2187 size_vector_unsigned_byte_2;
2188 sizetab[SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG] =
2189 size_vector_unsigned_byte_4;
2190 sizetab[SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG] =
2191 size_vector_unsigned_byte_8;
2192 sizetab[SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG] =
2193 size_vector_unsigned_byte_16;
2194 sizetab[SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG] =
2195 size_vector_unsigned_byte_32;
2196 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
2197 sizetab[SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG] =
2198 size_vector_unsigned_byte_8;
2200 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
2201 sizetab[SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG] =
2202 size_vector_unsigned_byte_16;
2204 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
2205 sizetab[SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG] =
2206 size_vector_unsigned_byte_32;
2208 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
2209 sizetab[SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG] =
2210 size_vector_unsigned_byte_32;
2212 sizetab[SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG] = size_vector_single_float;
2213 sizetab[SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG] = size_vector_double_float;
2214 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
2215 sizetab[SIMPLE_ARRAY_LONG_FLOAT_WIDETAG] = size_vector_long_float;
2217 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
2218 sizetab[SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG] =
2219 size_vector_complex_single_float;
2221 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
2222 sizetab[SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG] =
2223 size_vector_complex_double_float;
2225 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
2226 sizetab[SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG] =
2227 size_vector_complex_long_float;
2229 sizetab[COMPLEX_STRING_WIDETAG] = size_boxed;
2230 sizetab[COMPLEX_BIT_VECTOR_WIDETAG] = size_boxed;
2231 sizetab[COMPLEX_VECTOR_WIDETAG] = size_boxed;
2232 sizetab[COMPLEX_ARRAY_WIDETAG] = size_boxed;
2233 sizetab[CODE_HEADER_WIDETAG] = size_code_header;
2235 /* Shouldn't see these so just lose if it happens */
2236 sizetab[SIMPLE_FUN_HEADER_WIDETAG] = size_function_header;
2237 sizetab[CLOSURE_FUN_HEADER_WIDETAG] = size_function_header;
2238 sizetab[RETURN_PC_HEADER_WIDETAG] = size_return_pc_header;
2240 sizetab[CLOSURE_HEADER_WIDETAG] = size_boxed;
2241 sizetab[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = size_boxed;
2242 sizetab[VALUE_CELL_HEADER_WIDETAG] = size_boxed;
2243 sizetab[SYMBOL_HEADER_WIDETAG] = size_boxed;
2244 sizetab[BASE_CHAR_WIDETAG] = size_immediate;
2245 sizetab[SAP_WIDETAG] = size_unboxed;
2246 sizetab[UNBOUND_MARKER_WIDETAG] = size_immediate;
2247 sizetab[WEAK_POINTER_WIDETAG] = size_weak_pointer;
2248 sizetab[INSTANCE_HEADER_WIDETAG] = size_boxed;
2249 sizetab[FDEFN_WIDETAG] = size_boxed;
2252 /* noise to manipulate the gc trigger stuff */
2254 void set_auto_gc_trigger(os_vm_size_t dynamic_usage)
2256 os_vm_address_t addr=(os_vm_address_t)current_dynamic_space
2259 long length = DYNAMIC_SPACE_SIZE - dynamic_usage;
2261 if (addr < (os_vm_address_t)dynamic_space_free_pointer) {
2263 "set_auto_gc_trigger: tried to set gc trigger too low! (%d < %p)\n",
2264 (unsigned int)dynamic_usage,
2265 (os_vm_address_t)dynamic_space_free_pointer
2266 - (os_vm_address_t)current_dynamic_space);
2269 else if (length < 0) {
2271 "set_auto_gc_trigger: tried to set gc trigger too high! (%p)\n",
2276 addr=os_round_up_to_page(addr);
2277 length=os_trunc_size_to_page(length);
2279 #if defined(SUNOS) || defined(SOLARIS)
2280 os_invalidate(addr,length);
2282 os_protect(addr, length, 0);
2285 current_auto_gc_trigger = (lispobj *)addr;
2288 void clear_auto_gc_trigger(void)
2290 if (current_auto_gc_trigger!=NULL){
2291 #if defined(SUNOS) || defined(SOLARIS)/* don't want to force whole space into swapping mode... */
2292 os_vm_address_t addr=(os_vm_address_t)current_auto_gc_trigger;
2293 os_vm_size_t length=
2294 DYNAMIC_SPACE_SIZE + (os_vm_address_t)current_dynamic_space - addr;
2296 os_validate(addr,length);
2298 os_protect((os_vm_address_t)current_dynamic_space,
2303 current_auto_gc_trigger = NULL;