0.9.5.51:
[sbcl.git] / src / runtime / gencgc.c
1 /*
2  * GENerational Conservative Garbage Collector for SBCL x86
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 /*
17  * For a review of garbage collection techniques (e.g. generational
18  * GC) and terminology (e.g. "scavenging") see Paul R. Wilson,
19  * "Uniprocessor Garbage Collection Techniques". As of 20000618, this
20  * had been accepted for _ACM Computing Surveys_ and was available
21  * as a PostScript preprint through
22  *   <http://www.cs.utexas.edu/users/oops/papers.html>
23  * as
24  *   <ftp://ftp.cs.utexas.edu/pub/garbage/bigsurv.ps>.
25  */
26
27 #include <stdio.h>
28 #include <signal.h>
29 #include <errno.h>
30 #include <string.h>
31 #include "sbcl.h"
32 #include "runtime.h"
33 #include "os.h"
34 #include "interr.h"
35 #include "globals.h"
36 #include "interrupt.h"
37 #include "validate.h"
38 #include "lispregs.h"
39 #include "arch.h"
40 #include "fixnump.h"
41 #include "gc.h"
42 #include "gc-internal.h"
43 #include "thread.h"
44 #include "genesis/vector.h"
45 #include "genesis/weak-pointer.h"
46 #include "genesis/simple-fun.h"
47 #include "save.h"
48 #include "genesis/hash-table.h"
49
50 /* forward declarations */
51 page_index_t  gc_find_freeish_pages(long *restart_page_ptr, long nbytes,
52                                     int unboxed);
53
54 \f
55 /*
56  * GC parameters
57  */
58
59 /* Generations 0-5 are normal collected generations, 6 is only used as
60  * scratch space by the collector, and should never get collected.
61  */
62 enum {
63     HIGHEST_NORMAL_GENERATION = 5,
64     PSEUDO_STATIC_GENERATION = 5,
65     SCRATCH_GENERATION,
66     NUM_GENERATIONS
67 };
68
69 /* Should we use page protection to help avoid the scavenging of pages
70  * that don't have pointers to younger generations? */
71 boolean enable_page_protection = 1;
72
73 /* Should we unmap a page and re-mmap it to have it zero filled? */
74 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun)
75 /* comment from cmucl-2.4.8: This can waste a lot of swap on FreeBSD
76  * so don't unmap there.
77  *
78  * The CMU CL comment didn't specify a version, but was probably an
79  * old version of FreeBSD (pre-4.0), so this might no longer be true.
80  * OTOH, if it is true, this behavior might exist on OpenBSD too, so
81  * for now we don't unmap there either. -- WHN 2001-04-07 */
82 /* Apparently this flag is required to be 0 for SunOS/x86, as there
83  * are reports of heap corruption otherwise. */
84 boolean gencgc_unmap_zero = 0;
85 #else
86 boolean gencgc_unmap_zero = 1;
87 #endif
88
89 /* the minimum size (in bytes) for a large object*/
90 unsigned long large_object_size = 4 * PAGE_BYTES;
91
92 \f
93 /*
94  * debugging
95  */
96
97
98
99 /* the verbosity level. All non-error messages are disabled at level 0;
100  * and only a few rare messages are printed at level 1. */
101 #ifdef QSHOW
102 boolean gencgc_verbose = 1;
103 #else
104 boolean gencgc_verbose = 0;
105 #endif
106
107 /* FIXME: At some point enable the various error-checking things below
108  * and see what they say. */
109
110 /* We hunt for pointers to old-space, when GCing generations >= verify_gen.
111  * Set verify_gens to HIGHEST_NORMAL_GENERATION + 1 to disable this kind of
112  * check. */
113 generation_index_t verify_gens = HIGHEST_NORMAL_GENERATION + 1;
114
115 /* Should we do a pre-scan verify of generation 0 before it's GCed? */
116 boolean pre_verify_gen_0 = 0;
117
118 /* Should we check for bad pointers after gc_free_heap is called
119  * from Lisp PURIFY? */
120 boolean verify_after_free_heap = 0;
121
122 /* Should we print a note when code objects are found in the dynamic space
123  * during a heap verify? */
124 boolean verify_dynamic_code_check = 0;
125
126 /* Should we check code objects for fixup errors after they are transported? */
127 boolean check_code_fixups = 0;
128
129 /* Should we check that newly allocated regions are zero filled? */
130 boolean gencgc_zero_check = 0;
131
132 /* Should we check that the free space is zero filled? */
133 boolean gencgc_enable_verify_zero_fill = 0;
134
135 /* Should we check that free pages are zero filled during gc_free_heap
136  * called after Lisp PURIFY? */
137 boolean gencgc_zero_check_during_free_heap = 0;
138 \f
139 /*
140  * GC structures and variables
141  */
142
143 /* the total bytes allocated. These are seen by Lisp DYNAMIC-USAGE. */
144 unsigned long bytes_allocated = 0;
145 extern unsigned long bytes_consed_between_gcs; /* gc-common.c */
146 unsigned long auto_gc_trigger = 0;
147
148 /* the source and destination generations. These are set before a GC starts
149  * scavenging. */
150 generation_index_t from_space;
151 generation_index_t new_space;
152
153 /* should the GC be conservative on stack. If false (only right before
154  * saving a core), don't scan the stack / mark pages dont_move. */
155 static boolean conservative_stack = 1;
156
157 /* An array of page structures is statically allocated.
158  * This helps quickly map between an address its page structure.
159  * NUM_PAGES is set from the size of the dynamic space. */
160 struct page page_table[NUM_PAGES];
161
162 /* To map addresses to page structures the address of the first page
163  * is needed. */
164 static void *heap_base = NULL;
165
166 #if N_WORD_BITS == 32
167  #define SIMPLE_ARRAY_WORD_WIDETAG SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG
168 #elif N_WORD_BITS == 64
169  #define SIMPLE_ARRAY_WORD_WIDETAG SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG
170 #endif
171
172 /* Calculate the start address for the given page number. */
173 inline void *
174 page_address(page_index_t page_num)
175 {
176     return (heap_base + (page_num * PAGE_BYTES));
177 }
178
179 /* Find the page index within the page_table for the given
180  * address. Return -1 on failure. */
181 inline page_index_t
182 find_page_index(void *addr)
183 {
184     page_index_t index = addr-heap_base;
185
186     if (index >= 0) {
187         index = ((unsigned long)index)/PAGE_BYTES;
188         if (index < NUM_PAGES)
189             return (index);
190     }
191
192     return (-1);
193 }
194
195 /* a structure to hold the state of a generation */
196 struct generation {
197
198     /* the first page that gc_alloc() checks on its next call */
199     page_index_t alloc_start_page;
200
201     /* the first page that gc_alloc_unboxed() checks on its next call */
202     page_index_t alloc_unboxed_start_page;
203
204     /* the first page that gc_alloc_large (boxed) considers on its next
205      * call. (Although it always allocates after the boxed_region.) */
206     page_index_t alloc_large_start_page;
207
208     /* the first page that gc_alloc_large (unboxed) considers on its
209      * next call. (Although it always allocates after the
210      * current_unboxed_region.) */
211     page_index_t alloc_large_unboxed_start_page;
212
213     /* the bytes allocated to this generation */
214     long bytes_allocated;
215
216     /* the number of bytes at which to trigger a GC */
217     long gc_trigger;
218
219     /* to calculate a new level for gc_trigger */
220     long bytes_consed_between_gc;
221
222     /* the number of GCs since the last raise */
223     int num_gc;
224
225     /* the average age after which a GC will raise objects to the
226      * next generation */
227     int trigger_age;
228
229     /* the cumulative sum of the bytes allocated to this generation. It is
230      * cleared after a GC on this generations, and update before new
231      * objects are added from a GC of a younger generation. Dividing by
232      * the bytes_allocated will give the average age of the memory in
233      * this generation since its last GC. */
234     long cum_sum_bytes_allocated;
235
236     /* a minimum average memory age before a GC will occur helps
237      * prevent a GC when a large number of new live objects have been
238      * added, in which case a GC could be a waste of time */
239     double min_av_mem_age;
240 };
241
242 /* an array of generation structures. There needs to be one more
243  * generation structure than actual generations as the oldest
244  * generation is temporarily raised then lowered. */
245 struct generation generations[NUM_GENERATIONS];
246
247 /* the oldest generation that is will currently be GCed by default.
248  * Valid values are: 0, 1, ... HIGHEST_NORMAL_GENERATION
249  *
250  * The default of HIGHEST_NORMAL_GENERATION enables GC on all generations.
251  *
252  * Setting this to 0 effectively disables the generational nature of
253  * the GC. In some applications generational GC may not be useful
254  * because there are no long-lived objects.
255  *
256  * An intermediate value could be handy after moving long-lived data
257  * into an older generation so an unnecessary GC of this long-lived
258  * data can be avoided. */
259 generation_index_t gencgc_oldest_gen_to_gc = HIGHEST_NORMAL_GENERATION;
260
261 /* The maximum free page in the heap is maintained and used to update
262  * ALLOCATION_POINTER which is used by the room function to limit its
263  * search of the heap. XX Gencgc obviously needs to be better
264  * integrated with the Lisp code. */
265 page_index_t last_free_page;
266 \f
267 /* This lock is to prevent multiple threads from simultaneously
268  * allocating new regions which overlap each other.  Note that the
269  * majority of GC is single-threaded, but alloc() may be called from
270  * >1 thread at a time and must be thread-safe.  This lock must be
271  * seized before all accesses to generations[] or to parts of
272  * page_table[] that other threads may want to see */
273
274 #ifdef LISP_FEATURE_SB_THREAD
275 static pthread_mutex_t free_pages_lock = PTHREAD_MUTEX_INITIALIZER;
276 #endif
277
278 \f
279 /*
280  * miscellaneous heap functions
281  */
282
283 /* Count the number of pages which are write-protected within the
284  * given generation. */
285 static long
286 count_write_protect_generation_pages(generation_index_t generation)
287 {
288     page_index_t i;
289     long count = 0;
290
291     for (i = 0; i < last_free_page; i++)
292         if ((page_table[i].allocated != FREE_PAGE_FLAG)
293             && (page_table[i].gen == generation)
294             && (page_table[i].write_protected == 1))
295             count++;
296     return count;
297 }
298
299 /* Count the number of pages within the given generation. */
300 static long
301 count_generation_pages(generation_index_t generation)
302 {
303     page_index_t i;
304     long count = 0;
305
306     for (i = 0; i < last_free_page; i++)
307         if ((page_table[i].allocated != 0)
308             && (page_table[i].gen == generation))
309             count++;
310     return count;
311 }
312
313 #ifdef QSHOW
314 static long
315 count_dont_move_pages(void)
316 {
317     page_index_t i;
318     long count = 0;
319     for (i = 0; i < last_free_page; i++) {
320         if ((page_table[i].allocated != 0) && (page_table[i].dont_move != 0)) {
321             ++count;
322         }
323     }
324     return count;
325 }
326 #endif /* QSHOW */
327
328 /* Work through the pages and add up the number of bytes used for the
329  * given generation. */
330 static long
331 count_generation_bytes_allocated (generation_index_t gen)
332 {
333     page_index_t i;
334     long result = 0;
335     for (i = 0; i < last_free_page; i++) {
336         if ((page_table[i].allocated != 0) && (page_table[i].gen == gen))
337             result += page_table[i].bytes_used;
338     }
339     return result;
340 }
341
342 /* Return the average age of the memory in a generation. */
343 static double
344 gen_av_mem_age(int gen)
345 {
346     if (generations[gen].bytes_allocated == 0)
347         return 0.0;
348
349     return
350         ((double)generations[gen].cum_sum_bytes_allocated)
351         / ((double)generations[gen].bytes_allocated);
352 }
353
354 void fpu_save(int *);           /* defined in x86-assem.S */
355 void fpu_restore(int *);        /* defined in x86-assem.S */
356 /* The verbose argument controls how much to print: 0 for normal
357  * level of detail; 1 for debugging. */
358 static void
359 print_generation_stats(int verbose) /* FIXME: should take FILE argument */
360 {
361     int i, gens;
362     int fpu_state[27];
363
364     /* This code uses the FP instructions which may be set up for Lisp
365      * so they need to be saved and reset for C. */
366     fpu_save(fpu_state);
367
368     /* highest generation to print */
369     if (verbose)
370         gens = SCRATCH_GENERATION;
371     else
372         gens = PSEUDO_STATIC_GENERATION;
373
374     /* Print the heap stats. */
375     fprintf(stderr,
376             "   Gen Boxed Unboxed LB   LUB  !move  Alloc  Waste   Trig    WP  GCs Mem-age\n");
377
378     for (i = 0; i < gens; i++) {
379         page_index_t j;
380         long boxed_cnt = 0;
381         long unboxed_cnt = 0;
382         long large_boxed_cnt = 0;
383         long large_unboxed_cnt = 0;
384         long pinned_cnt=0;
385
386         for (j = 0; j < last_free_page; j++)
387             if (page_table[j].gen == i) {
388
389                 /* Count the number of boxed pages within the given
390                  * generation. */
391                 if (page_table[j].allocated & BOXED_PAGE_FLAG) {
392                     if (page_table[j].large_object)
393                         large_boxed_cnt++;
394                     else
395                         boxed_cnt++;
396                 }
397                 if(page_table[j].dont_move) pinned_cnt++;
398                 /* Count the number of unboxed pages within the given
399                  * generation. */
400                 if (page_table[j].allocated & UNBOXED_PAGE_FLAG) {
401                     if (page_table[j].large_object)
402                         large_unboxed_cnt++;
403                     else
404                         unboxed_cnt++;
405                 }
406             }
407
408         gc_assert(generations[i].bytes_allocated
409                   == count_generation_bytes_allocated(i));
410         fprintf(stderr,
411                 "   %1d: %5ld %5ld %5ld %5ld %5ld %8ld %5ld %8ld %4ld %3d %7.4f\n",
412                 i,
413                 boxed_cnt, unboxed_cnt, large_boxed_cnt, large_unboxed_cnt,
414                 pinned_cnt,
415                 generations[i].bytes_allocated,
416                 (count_generation_pages(i)*PAGE_BYTES
417                  - generations[i].bytes_allocated),
418                 generations[i].gc_trigger,
419                 count_write_protect_generation_pages(i),
420                 generations[i].num_gc,
421                 gen_av_mem_age(i));
422     }
423     fprintf(stderr,"   Total bytes allocated=%ld\n", bytes_allocated);
424
425     fpu_restore(fpu_state);
426 }
427 \f
428 /*
429  * allocation routines
430  */
431
432 /*
433  * To support quick and inline allocation, regions of memory can be
434  * allocated and then allocated from with just a free pointer and a
435  * check against an end address.
436  *
437  * Since objects can be allocated to spaces with different properties
438  * e.g. boxed/unboxed, generation, ages; there may need to be many
439  * allocation regions.
440  *
441  * Each allocation region may start within a partly used page. Many
442  * features of memory use are noted on a page wise basis, e.g. the
443  * generation; so if a region starts within an existing allocated page
444  * it must be consistent with this page.
445  *
446  * During the scavenging of the newspace, objects will be transported
447  * into an allocation region, and pointers updated to point to this
448  * allocation region. It is possible that these pointers will be
449  * scavenged again before the allocation region is closed, e.g. due to
450  * trans_list which jumps all over the place to cleanup the list. It
451  * is important to be able to determine properties of all objects
452  * pointed to when scavenging, e.g to detect pointers to the oldspace.
453  * Thus it's important that the allocation regions have the correct
454  * properties set when allocated, and not just set when closed. The
455  * region allocation routines return regions with the specified
456  * properties, and grab all the pages, setting their properties
457  * appropriately, except that the amount used is not known.
458  *
459  * These regions are used to support quicker allocation using just a
460  * free pointer. The actual space used by the region is not reflected
461  * in the pages tables until it is closed. It can't be scavenged until
462  * closed.
463  *
464  * When finished with the region it should be closed, which will
465  * update the page tables for the actual space used returning unused
466  * space. Further it may be noted in the new regions which is
467  * necessary when scavenging the newspace.
468  *
469  * Large objects may be allocated directly without an allocation
470  * region, the page tables are updated immediately.
471  *
472  * Unboxed objects don't contain pointers to other objects and so
473  * don't need scavenging. Further they can't contain pointers to
474  * younger generations so WP is not needed. By allocating pages to
475  * unboxed objects the whole page never needs scavenging or
476  * write-protecting. */
477
478 /* We are only using two regions at present. Both are for the current
479  * newspace generation. */
480 struct alloc_region boxed_region;
481 struct alloc_region unboxed_region;
482
483 /* The generation currently being allocated to. */
484 static generation_index_t gc_alloc_generation;
485
486 /* Find a new region with room for at least the given number of bytes.
487  *
488  * It starts looking at the current generation's alloc_start_page. So
489  * may pick up from the previous region if there is enough space. This
490  * keeps the allocation contiguous when scavenging the newspace.
491  *
492  * The alloc_region should have been closed by a call to
493  * gc_alloc_update_page_tables(), and will thus be in an empty state.
494  *
495  * To assist the scavenging functions write-protected pages are not
496  * used. Free pages should not be write-protected.
497  *
498  * It is critical to the conservative GC that the start of regions be
499  * known. To help achieve this only small regions are allocated at a
500  * time.
501  *
502  * During scavenging, pointers may be found to within the current
503  * region and the page generation must be set so that pointers to the
504  * from space can be recognized. Therefore the generation of pages in
505  * the region are set to gc_alloc_generation. To prevent another
506  * allocation call using the same pages, all the pages in the region
507  * are allocated, although they will initially be empty.
508  */
509 static void
510 gc_alloc_new_region(long nbytes, int unboxed, struct alloc_region *alloc_region)
511 {
512     page_index_t first_page;
513     page_index_t last_page;
514     long bytes_found;
515     page_index_t i;
516
517     /*
518     FSHOW((stderr,
519            "/alloc_new_region for %d bytes from gen %d\n",
520            nbytes, gc_alloc_generation));
521     */
522
523     /* Check that the region is in a reset state. */
524     gc_assert((alloc_region->first_page == 0)
525               && (alloc_region->last_page == -1)
526               && (alloc_region->free_pointer == alloc_region->end_addr));
527     thread_mutex_lock(&free_pages_lock);
528     if (unboxed) {
529         first_page =
530             generations[gc_alloc_generation].alloc_unboxed_start_page;
531     } else {
532         first_page =
533             generations[gc_alloc_generation].alloc_start_page;
534     }
535     last_page=gc_find_freeish_pages(&first_page,nbytes,unboxed);
536     bytes_found=(PAGE_BYTES - page_table[first_page].bytes_used)
537             + PAGE_BYTES*(last_page-first_page);
538
539     /* Set up the alloc_region. */
540     alloc_region->first_page = first_page;
541     alloc_region->last_page = last_page;
542     alloc_region->start_addr = page_table[first_page].bytes_used
543         + page_address(first_page);
544     alloc_region->free_pointer = alloc_region->start_addr;
545     alloc_region->end_addr = alloc_region->start_addr + bytes_found;
546
547     /* Set up the pages. */
548
549     /* The first page may have already been in use. */
550     if (page_table[first_page].bytes_used == 0) {
551         if (unboxed)
552             page_table[first_page].allocated = UNBOXED_PAGE_FLAG;
553         else
554             page_table[first_page].allocated = BOXED_PAGE_FLAG;
555         page_table[first_page].gen = gc_alloc_generation;
556         page_table[first_page].large_object = 0;
557         page_table[first_page].first_object_offset = 0;
558     }
559
560     if (unboxed)
561         gc_assert(page_table[first_page].allocated == UNBOXED_PAGE_FLAG);
562     else
563         gc_assert(page_table[first_page].allocated == BOXED_PAGE_FLAG);
564     page_table[first_page].allocated |= OPEN_REGION_PAGE_FLAG;
565
566     gc_assert(page_table[first_page].gen == gc_alloc_generation);
567     gc_assert(page_table[first_page].large_object == 0);
568
569     for (i = first_page+1; i <= last_page; i++) {
570         if (unboxed)
571             page_table[i].allocated = UNBOXED_PAGE_FLAG;
572         else
573             page_table[i].allocated = BOXED_PAGE_FLAG;
574         page_table[i].gen = gc_alloc_generation;
575         page_table[i].large_object = 0;
576         /* This may not be necessary for unboxed regions (think it was
577          * broken before!) */
578         page_table[i].first_object_offset =
579             alloc_region->start_addr - page_address(i);
580         page_table[i].allocated |= OPEN_REGION_PAGE_FLAG ;
581     }
582     /* Bump up last_free_page. */
583     if (last_page+1 > last_free_page) {
584         last_free_page = last_page+1;
585         SetSymbolValue(ALLOCATION_POINTER,
586                        (lispobj)(((char *)heap_base) + last_free_page*PAGE_BYTES),
587                        0);
588     }
589     thread_mutex_unlock(&free_pages_lock);
590
591     /* we can do this after releasing free_pages_lock */
592     if (gencgc_zero_check) {
593         long *p;
594         for (p = (long *)alloc_region->start_addr;
595              p < (long *)alloc_region->end_addr; p++) {
596             if (*p != 0) {
597                 /* KLUDGE: It would be nice to use %lx and explicit casts
598                  * (long) in code like this, so that it is less likely to
599                  * break randomly when running on a machine with different
600                  * word sizes. -- WHN 19991129 */
601                 lose("The new region at %x is not zero.", p);
602             }
603     }
604 }
605
606 }
607
608 /* If the record_new_objects flag is 2 then all new regions created
609  * are recorded.
610  *
611  * If it's 1 then then it is only recorded if the first page of the
612  * current region is <= new_areas_ignore_page. This helps avoid
613  * unnecessary recording when doing full scavenge pass.
614  *
615  * The new_object structure holds the page, byte offset, and size of
616  * new regions of objects. Each new area is placed in the array of
617  * these structures pointer to by new_areas. new_areas_index holds the
618  * offset into new_areas.
619  *
620  * If new_area overflows NUM_NEW_AREAS then it stops adding them. The
621  * later code must detect this and handle it, probably by doing a full
622  * scavenge of a generation. */
623 #define NUM_NEW_AREAS 512
624 static int record_new_objects = 0;
625 static page_index_t new_areas_ignore_page;
626 struct new_area {
627     page_index_t page;
628     long  offset;
629     long  size;
630 };
631 static struct new_area (*new_areas)[];
632 static long new_areas_index;
633 long max_new_areas;
634
635 /* Add a new area to new_areas. */
636 static void
637 add_new_area(page_index_t first_page, long offset, long size)
638 {
639     unsigned long new_area_start,c;
640     long i;
641
642     /* Ignore if full. */
643     if (new_areas_index >= NUM_NEW_AREAS)
644         return;
645
646     switch (record_new_objects) {
647     case 0:
648         return;
649     case 1:
650         if (first_page > new_areas_ignore_page)
651             return;
652         break;
653     case 2:
654         break;
655     default:
656         gc_abort();
657     }
658
659     new_area_start = PAGE_BYTES*first_page + offset;
660
661     /* Search backwards for a prior area that this follows from. If
662        found this will save adding a new area. */
663     for (i = new_areas_index-1, c = 0; (i >= 0) && (c < 8); i--, c++) {
664         unsigned long area_end =
665             PAGE_BYTES*((*new_areas)[i].page)
666             + (*new_areas)[i].offset
667             + (*new_areas)[i].size;
668         /*FSHOW((stderr,
669                "/add_new_area S1 %d %d %d %d\n",
670                i, c, new_area_start, area_end));*/
671         if (new_area_start == area_end) {
672             /*FSHOW((stderr,
673                    "/adding to [%d] %d %d %d with %d %d %d:\n",
674                    i,
675                    (*new_areas)[i].page,
676                    (*new_areas)[i].offset,
677                    (*new_areas)[i].size,
678                    first_page,
679                    offset,
680                     size);*/
681             (*new_areas)[i].size += size;
682             return;
683         }
684     }
685
686     (*new_areas)[new_areas_index].page = first_page;
687     (*new_areas)[new_areas_index].offset = offset;
688     (*new_areas)[new_areas_index].size = size;
689     /*FSHOW((stderr,
690            "/new_area %d page %d offset %d size %d\n",
691            new_areas_index, first_page, offset, size));*/
692     new_areas_index++;
693
694     /* Note the max new_areas used. */
695     if (new_areas_index > max_new_areas)
696         max_new_areas = new_areas_index;
697 }
698
699 /* Update the tables for the alloc_region. The region may be added to
700  * the new_areas.
701  *
702  * When done the alloc_region is set up so that the next quick alloc
703  * will fail safely and thus a new region will be allocated. Further
704  * it is safe to try to re-update the page table of this reset
705  * alloc_region. */
706 void
707 gc_alloc_update_page_tables(int unboxed, struct alloc_region *alloc_region)
708 {
709     int more;
710     page_index_t first_page;
711     page_index_t next_page;
712     int bytes_used;
713     long orig_first_page_bytes_used;
714     long region_size;
715     long byte_cnt;
716
717
718     first_page = alloc_region->first_page;
719
720     /* Catch an unused alloc_region. */
721     if ((first_page == 0) && (alloc_region->last_page == -1))
722         return;
723
724     next_page = first_page+1;
725
726     thread_mutex_lock(&free_pages_lock);
727     if (alloc_region->free_pointer != alloc_region->start_addr) {
728         /* some bytes were allocated in the region */
729         orig_first_page_bytes_used = page_table[first_page].bytes_used;
730
731         gc_assert(alloc_region->start_addr == (page_address(first_page) + page_table[first_page].bytes_used));
732
733         /* All the pages used need to be updated */
734
735         /* Update the first page. */
736
737         /* If the page was free then set up the gen, and
738          * first_object_offset. */
739         if (page_table[first_page].bytes_used == 0)
740             gc_assert(page_table[first_page].first_object_offset == 0);
741         page_table[first_page].allocated &= ~(OPEN_REGION_PAGE_FLAG);
742
743         if (unboxed)
744             gc_assert(page_table[first_page].allocated == UNBOXED_PAGE_FLAG);
745         else
746             gc_assert(page_table[first_page].allocated == BOXED_PAGE_FLAG);
747         gc_assert(page_table[first_page].gen == gc_alloc_generation);
748         gc_assert(page_table[first_page].large_object == 0);
749
750         byte_cnt = 0;
751
752         /* Calculate the number of bytes used in this page. This is not
753          * always the number of new bytes, unless it was free. */
754         more = 0;
755         if ((bytes_used = (alloc_region->free_pointer - page_address(first_page)))>PAGE_BYTES) {
756             bytes_used = PAGE_BYTES;
757             more = 1;
758         }
759         page_table[first_page].bytes_used = bytes_used;
760         byte_cnt += bytes_used;
761
762
763         /* All the rest of the pages should be free. We need to set their
764          * first_object_offset pointer to the start of the region, and set
765          * the bytes_used. */
766         while (more) {
767             page_table[next_page].allocated &= ~(OPEN_REGION_PAGE_FLAG);
768             if (unboxed)
769                 gc_assert(page_table[next_page].allocated==UNBOXED_PAGE_FLAG);
770             else
771                 gc_assert(page_table[next_page].allocated == BOXED_PAGE_FLAG);
772             gc_assert(page_table[next_page].bytes_used == 0);
773             gc_assert(page_table[next_page].gen == gc_alloc_generation);
774             gc_assert(page_table[next_page].large_object == 0);
775
776             gc_assert(page_table[next_page].first_object_offset ==
777                       alloc_region->start_addr - page_address(next_page));
778
779             /* Calculate the number of bytes used in this page. */
780             more = 0;
781             if ((bytes_used = (alloc_region->free_pointer
782                                - page_address(next_page)))>PAGE_BYTES) {
783                 bytes_used = PAGE_BYTES;
784                 more = 1;
785             }
786             page_table[next_page].bytes_used = bytes_used;
787             byte_cnt += bytes_used;
788
789             next_page++;
790         }
791
792         region_size = alloc_region->free_pointer - alloc_region->start_addr;
793         bytes_allocated += region_size;
794         generations[gc_alloc_generation].bytes_allocated += region_size;
795
796         gc_assert((byte_cnt- orig_first_page_bytes_used) == region_size);
797
798         /* Set the generations alloc restart page to the last page of
799          * the region. */
800         if (unboxed)
801             generations[gc_alloc_generation].alloc_unboxed_start_page =
802                 next_page-1;
803         else
804             generations[gc_alloc_generation].alloc_start_page = next_page-1;
805
806         /* Add the region to the new_areas if requested. */
807         if (!unboxed)
808             add_new_area(first_page,orig_first_page_bytes_used, region_size);
809
810         /*
811         FSHOW((stderr,
812                "/gc_alloc_update_page_tables update %d bytes to gen %d\n",
813                region_size,
814                gc_alloc_generation));
815         */
816     } else {
817         /* There are no bytes allocated. Unallocate the first_page if
818          * there are 0 bytes_used. */
819         page_table[first_page].allocated &= ~(OPEN_REGION_PAGE_FLAG);
820         if (page_table[first_page].bytes_used == 0)
821             page_table[first_page].allocated = FREE_PAGE_FLAG;
822     }
823
824     /* Unallocate any unused pages. */
825     while (next_page <= alloc_region->last_page) {
826         gc_assert(page_table[next_page].bytes_used == 0);
827         page_table[next_page].allocated = FREE_PAGE_FLAG;
828         next_page++;
829     }
830     thread_mutex_unlock(&free_pages_lock);
831     /* alloc_region is per-thread, we're ok to do this unlocked */
832     gc_set_region_empty(alloc_region);
833 }
834
835 static inline void *gc_quick_alloc(long nbytes);
836
837 /* Allocate a possibly large object. */
838 void *
839 gc_alloc_large(long nbytes, int unboxed, struct alloc_region *alloc_region)
840 {
841     page_index_t first_page;
842     page_index_t last_page;
843     int orig_first_page_bytes_used;
844     long byte_cnt;
845     int more;
846     long bytes_used;
847     page_index_t next_page;
848
849     thread_mutex_lock(&free_pages_lock);
850
851     if (unboxed) {
852         first_page =
853             generations[gc_alloc_generation].alloc_large_unboxed_start_page;
854     } else {
855         first_page = generations[gc_alloc_generation].alloc_large_start_page;
856     }
857     if (first_page <= alloc_region->last_page) {
858         first_page = alloc_region->last_page+1;
859     }
860
861     last_page=gc_find_freeish_pages(&first_page,nbytes,unboxed);
862
863     gc_assert(first_page > alloc_region->last_page);
864     if (unboxed)
865         generations[gc_alloc_generation].alloc_large_unboxed_start_page =
866             last_page;
867     else
868         generations[gc_alloc_generation].alloc_large_start_page = last_page;
869
870     /* Set up the pages. */
871     orig_first_page_bytes_used = page_table[first_page].bytes_used;
872
873     /* If the first page was free then set up the gen, and
874      * first_object_offset. */
875     if (page_table[first_page].bytes_used == 0) {
876         if (unboxed)
877             page_table[first_page].allocated = UNBOXED_PAGE_FLAG;
878         else
879             page_table[first_page].allocated = BOXED_PAGE_FLAG;
880         page_table[first_page].gen = gc_alloc_generation;
881         page_table[first_page].first_object_offset = 0;
882         page_table[first_page].large_object = 1;
883     }
884
885     if (unboxed)
886         gc_assert(page_table[first_page].allocated == UNBOXED_PAGE_FLAG);
887     else
888         gc_assert(page_table[first_page].allocated == BOXED_PAGE_FLAG);
889     gc_assert(page_table[first_page].gen == gc_alloc_generation);
890     gc_assert(page_table[first_page].large_object == 1);
891
892     byte_cnt = 0;
893
894     /* Calc. the number of bytes used in this page. This is not
895      * always the number of new bytes, unless it was free. */
896     more = 0;
897     if ((bytes_used = nbytes+orig_first_page_bytes_used) > PAGE_BYTES) {
898         bytes_used = PAGE_BYTES;
899         more = 1;
900     }
901     page_table[first_page].bytes_used = bytes_used;
902     byte_cnt += bytes_used;
903
904     next_page = first_page+1;
905
906     /* All the rest of the pages should be free. We need to set their
907      * first_object_offset pointer to the start of the region, and
908      * set the bytes_used. */
909     while (more) {
910         gc_assert(page_table[next_page].allocated == FREE_PAGE_FLAG);
911         gc_assert(page_table[next_page].bytes_used == 0);
912         if (unboxed)
913             page_table[next_page].allocated = UNBOXED_PAGE_FLAG;
914         else
915             page_table[next_page].allocated = BOXED_PAGE_FLAG;
916         page_table[next_page].gen = gc_alloc_generation;
917         page_table[next_page].large_object = 1;
918
919         page_table[next_page].first_object_offset =
920             orig_first_page_bytes_used - PAGE_BYTES*(next_page-first_page);
921
922         /* Calculate the number of bytes used in this page. */
923         more = 0;
924         if ((bytes_used=(nbytes+orig_first_page_bytes_used)-byte_cnt) > PAGE_BYTES) {
925             bytes_used = PAGE_BYTES;
926             more = 1;
927         }
928         page_table[next_page].bytes_used = bytes_used;
929         page_table[next_page].write_protected=0;
930         page_table[next_page].dont_move=0;
931         byte_cnt += bytes_used;
932         next_page++;
933     }
934
935     gc_assert((byte_cnt-orig_first_page_bytes_used) == nbytes);
936
937     bytes_allocated += nbytes;
938     generations[gc_alloc_generation].bytes_allocated += nbytes;
939
940     /* Add the region to the new_areas if requested. */
941     if (!unboxed)
942         add_new_area(first_page,orig_first_page_bytes_used,nbytes);
943
944     /* Bump up last_free_page */
945     if (last_page+1 > last_free_page) {
946         last_free_page = last_page+1;
947         SetSymbolValue(ALLOCATION_POINTER,
948                        (lispobj)(((char *)heap_base) + last_free_page*PAGE_BYTES),0);
949     }
950     thread_mutex_unlock(&free_pages_lock);
951
952     return((void *)(page_address(first_page)+orig_first_page_bytes_used));
953 }
954
955 long
956 gc_find_freeish_pages(long *restart_page_ptr, long nbytes, int unboxed)
957 {
958     page_index_t first_page;
959     page_index_t last_page;
960     long region_size;
961     page_index_t restart_page=*restart_page_ptr;
962     long bytes_found;
963     long num_pages;
964     int large_p=(nbytes>=large_object_size);
965     /* FIXME: assert(free_pages_lock is held); */
966
967     /* Search for a contiguous free space of at least nbytes. If it's
968      * a large object then align it on a page boundary by searching
969      * for a free page. */
970
971     do {
972         first_page = restart_page;
973         if (large_p)
974             while ((first_page < NUM_PAGES)
975                    && (page_table[first_page].allocated != FREE_PAGE_FLAG))
976                 first_page++;
977         else
978             while (first_page < NUM_PAGES) {
979                 if(page_table[first_page].allocated == FREE_PAGE_FLAG)
980                     break;
981                 if((page_table[first_page].allocated ==
982                     (unboxed ? UNBOXED_PAGE_FLAG : BOXED_PAGE_FLAG)) &&
983                    (page_table[first_page].large_object == 0) &&
984                    (page_table[first_page].gen == gc_alloc_generation) &&
985                    (page_table[first_page].bytes_used < (PAGE_BYTES-32)) &&
986                    (page_table[first_page].write_protected == 0) &&
987                    (page_table[first_page].dont_move == 0)) {
988                     break;
989                 }
990                 first_page++;
991             }
992
993         if (first_page >= NUM_PAGES) {
994             fprintf(stderr,
995                     "Argh! gc_find_free_space failed (first_page), nbytes=%ld.\n",
996                     nbytes);
997             print_generation_stats(1);
998             lose(NULL);
999         }
1000
1001         gc_assert(page_table[first_page].write_protected == 0);
1002
1003         last_page = first_page;
1004         bytes_found = PAGE_BYTES - page_table[first_page].bytes_used;
1005         num_pages = 1;
1006         while (((bytes_found < nbytes)
1007                 || (!large_p && (num_pages < 2)))
1008                && (last_page < (NUM_PAGES-1))
1009                && (page_table[last_page+1].allocated == FREE_PAGE_FLAG)) {
1010             last_page++;
1011             num_pages++;
1012             bytes_found += PAGE_BYTES;
1013             gc_assert(page_table[last_page].write_protected == 0);
1014         }
1015
1016         region_size = (PAGE_BYTES - page_table[first_page].bytes_used)
1017             + PAGE_BYTES*(last_page-first_page);
1018
1019         gc_assert(bytes_found == region_size);
1020         restart_page = last_page + 1;
1021     } while ((restart_page < NUM_PAGES) && (bytes_found < nbytes));
1022
1023     /* Check for a failure */
1024     if ((restart_page >= NUM_PAGES) && (bytes_found < nbytes)) {
1025         fprintf(stderr,
1026                 "Argh! gc_find_freeish_pages failed (restart_page), nbytes=%ld.\n",
1027                 nbytes);
1028         print_generation_stats(1);
1029         lose(NULL);
1030     }
1031     *restart_page_ptr=first_page;
1032     return last_page;
1033 }
1034
1035 /* Allocate bytes.  All the rest of the special-purpose allocation
1036  * functions will eventually call this  */
1037
1038 void *
1039 gc_alloc_with_region(long nbytes,int unboxed_p, struct alloc_region *my_region,
1040                      int quick_p)
1041 {
1042     void *new_free_pointer;
1043
1044     if(nbytes>=large_object_size)
1045         return gc_alloc_large(nbytes,unboxed_p,my_region);
1046
1047     /* Check whether there is room in the current alloc region. */
1048     new_free_pointer = my_region->free_pointer + nbytes;
1049
1050     /* fprintf(stderr, "alloc %d bytes from %p to %p\n", nbytes,
1051        my_region->free_pointer, new_free_pointer); */
1052
1053     if (new_free_pointer <= my_region->end_addr) {
1054         /* If so then allocate from the current alloc region. */
1055         void *new_obj = my_region->free_pointer;
1056         my_region->free_pointer = new_free_pointer;
1057
1058         /* Unless a `quick' alloc was requested, check whether the
1059            alloc region is almost empty. */
1060         if (!quick_p &&
1061             (my_region->end_addr - my_region->free_pointer) <= 32) {
1062             /* If so, finished with the current region. */
1063             gc_alloc_update_page_tables(unboxed_p, my_region);
1064             /* Set up a new region. */
1065             gc_alloc_new_region(32 /*bytes*/, unboxed_p, my_region);
1066         }
1067
1068         return((void *)new_obj);
1069     }
1070
1071     /* Else not enough free space in the current region: retry with a
1072      * new region. */
1073
1074     gc_alloc_update_page_tables(unboxed_p, my_region);
1075     gc_alloc_new_region(nbytes, unboxed_p, my_region);
1076     return gc_alloc_with_region(nbytes,unboxed_p,my_region,0);
1077 }
1078
1079 /* these are only used during GC: all allocation from the mutator calls
1080  * alloc() -> gc_alloc_with_region() with the appropriate per-thread
1081  * region */
1082
1083 void *
1084 gc_general_alloc(long nbytes,int unboxed_p,int quick_p)
1085 {
1086     struct alloc_region *my_region =
1087       unboxed_p ? &unboxed_region : &boxed_region;
1088     return gc_alloc_with_region(nbytes,unboxed_p, my_region,quick_p);
1089 }
1090
1091 static inline void *
1092 gc_quick_alloc(long nbytes)
1093 {
1094     return gc_general_alloc(nbytes,ALLOC_BOXED,ALLOC_QUICK);
1095 }
1096
1097 static inline void *
1098 gc_quick_alloc_large(long nbytes)
1099 {
1100     return gc_general_alloc(nbytes,ALLOC_BOXED,ALLOC_QUICK);
1101 }
1102
1103 static inline void *
1104 gc_alloc_unboxed(long nbytes)
1105 {
1106     return gc_general_alloc(nbytes,ALLOC_UNBOXED,0);
1107 }
1108
1109 static inline void *
1110 gc_quick_alloc_unboxed(long nbytes)
1111 {
1112     return gc_general_alloc(nbytes,ALLOC_UNBOXED,ALLOC_QUICK);
1113 }
1114
1115 static inline void *
1116 gc_quick_alloc_large_unboxed(long nbytes)
1117 {
1118     return gc_general_alloc(nbytes,ALLOC_UNBOXED,ALLOC_QUICK);
1119 }
1120 \f
1121 /*
1122  * scavenging/transporting routines derived from gc.c in CMU CL ca. 18b
1123  */
1124
1125 extern long (*scavtab[256])(lispobj *where, lispobj object);
1126 extern lispobj (*transother[256])(lispobj object);
1127 extern long (*sizetab[256])(lispobj *where);
1128
1129 /* Copy a large boxed object. If the object is in a large object
1130  * region then it is simply promoted, else it is copied. If it's large
1131  * enough then it's copied to a large object region.
1132  *
1133  * Vectors may have shrunk. If the object is not copied the space
1134  * needs to be reclaimed, and the page_tables corrected. */
1135 lispobj
1136 copy_large_object(lispobj object, long nwords)
1137 {
1138     int tag;
1139     lispobj *new;
1140     page_index_t first_page;
1141
1142     gc_assert(is_lisp_pointer(object));
1143     gc_assert(from_space_p(object));
1144     gc_assert((nwords & 0x01) == 0);
1145
1146
1147     /* Check whether it's in a large object region. */
1148     first_page = find_page_index((void *)object);
1149     gc_assert(first_page >= 0);
1150
1151     if (page_table[first_page].large_object) {
1152
1153         /* Promote the object. */
1154
1155         long remaining_bytes;
1156         page_index_t next_page;
1157         long bytes_freed;
1158         long old_bytes_used;
1159
1160         /* Note: Any page write-protection must be removed, else a
1161          * later scavenge_newspace may incorrectly not scavenge these
1162          * pages. This would not be necessary if they are added to the
1163          * new areas, but let's do it for them all (they'll probably
1164          * be written anyway?). */
1165
1166         gc_assert(page_table[first_page].first_object_offset == 0);
1167
1168         next_page = first_page;
1169         remaining_bytes = nwords*N_WORD_BYTES;
1170         while (remaining_bytes > PAGE_BYTES) {
1171             gc_assert(page_table[next_page].gen == from_space);
1172             gc_assert(page_table[next_page].allocated == BOXED_PAGE_FLAG);
1173             gc_assert(page_table[next_page].large_object);
1174             gc_assert(page_table[next_page].first_object_offset==
1175                       -PAGE_BYTES*(next_page-first_page));
1176             gc_assert(page_table[next_page].bytes_used == PAGE_BYTES);
1177
1178             page_table[next_page].gen = new_space;
1179
1180             /* Remove any write-protection. We should be able to rely
1181              * on the write-protect flag to avoid redundant calls. */
1182             if (page_table[next_page].write_protected) {
1183                 os_protect(page_address(next_page), PAGE_BYTES, OS_VM_PROT_ALL);
1184                 page_table[next_page].write_protected = 0;
1185             }
1186             remaining_bytes -= PAGE_BYTES;
1187             next_page++;
1188         }
1189
1190         /* Now only one page remains, but the object may have shrunk
1191          * so there may be more unused pages which will be freed. */
1192
1193         /* The object may have shrunk but shouldn't have grown. */
1194         gc_assert(page_table[next_page].bytes_used >= remaining_bytes);
1195
1196         page_table[next_page].gen = new_space;
1197         gc_assert(page_table[next_page].allocated == BOXED_PAGE_FLAG);
1198
1199         /* Adjust the bytes_used. */
1200         old_bytes_used = page_table[next_page].bytes_used;
1201         page_table[next_page].bytes_used = remaining_bytes;
1202
1203         bytes_freed = old_bytes_used - remaining_bytes;
1204
1205         /* Free any remaining pages; needs care. */
1206         next_page++;
1207         while ((old_bytes_used == PAGE_BYTES) &&
1208                (page_table[next_page].gen == from_space) &&
1209                (page_table[next_page].allocated == BOXED_PAGE_FLAG) &&
1210                page_table[next_page].large_object &&
1211                (page_table[next_page].first_object_offset ==
1212                 -(next_page - first_page)*PAGE_BYTES)) {
1213             /* Checks out OK, free the page. Don't need to bother zeroing
1214              * pages as this should have been done before shrinking the
1215              * object. These pages shouldn't be write-protected as they
1216              * should be zero filled. */
1217             gc_assert(page_table[next_page].write_protected == 0);
1218
1219             old_bytes_used = page_table[next_page].bytes_used;
1220             page_table[next_page].allocated = FREE_PAGE_FLAG;
1221             page_table[next_page].bytes_used = 0;
1222             bytes_freed += old_bytes_used;
1223             next_page++;
1224         }
1225
1226         generations[from_space].bytes_allocated -= N_WORD_BYTES*nwords +
1227           bytes_freed;
1228         generations[new_space].bytes_allocated += N_WORD_BYTES*nwords;
1229         bytes_allocated -= bytes_freed;
1230
1231         /* Add the region to the new_areas if requested. */
1232         add_new_area(first_page,0,nwords*N_WORD_BYTES);
1233
1234         return(object);
1235     } else {
1236         /* Get tag of object. */
1237         tag = lowtag_of(object);
1238
1239         /* Allocate space. */
1240         new = gc_quick_alloc_large(nwords*N_WORD_BYTES);
1241
1242         memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
1243
1244         /* Return Lisp pointer of new object. */
1245         return ((lispobj) new) | tag;
1246     }
1247 }
1248
1249 /* to copy unboxed objects */
1250 lispobj
1251 copy_unboxed_object(lispobj object, long nwords)
1252 {
1253     long tag;
1254     lispobj *new;
1255
1256     gc_assert(is_lisp_pointer(object));
1257     gc_assert(from_space_p(object));
1258     gc_assert((nwords & 0x01) == 0);
1259
1260     /* Get tag of object. */
1261     tag = lowtag_of(object);
1262
1263     /* Allocate space. */
1264     new = gc_quick_alloc_unboxed(nwords*N_WORD_BYTES);
1265
1266     memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
1267
1268     /* Return Lisp pointer of new object. */
1269     return ((lispobj) new) | tag;
1270 }
1271
1272 /* to copy large unboxed objects
1273  *
1274  * If the object is in a large object region then it is simply
1275  * promoted, else it is copied. If it's large enough then it's copied
1276  * to a large object region.
1277  *
1278  * Bignums and vectors may have shrunk. If the object is not copied
1279  * the space needs to be reclaimed, and the page_tables corrected.
1280  *
1281  * KLUDGE: There's a lot of cut-and-paste duplication between this
1282  * function and copy_large_object(..). -- WHN 20000619 */
1283 lispobj
1284 copy_large_unboxed_object(lispobj object, long nwords)
1285 {
1286     int tag;
1287     lispobj *new;
1288     page_index_t first_page;
1289
1290     gc_assert(is_lisp_pointer(object));
1291     gc_assert(from_space_p(object));
1292     gc_assert((nwords & 0x01) == 0);
1293
1294     if ((nwords > 1024*1024) && gencgc_verbose)
1295         FSHOW((stderr, "/copy_large_unboxed_object: %d bytes\n", nwords*N_WORD_BYTES));
1296
1297     /* Check whether it's a large object. */
1298     first_page = find_page_index((void *)object);
1299     gc_assert(first_page >= 0);
1300
1301     if (page_table[first_page].large_object) {
1302         /* Promote the object. Note: Unboxed objects may have been
1303          * allocated to a BOXED region so it may be necessary to
1304          * change the region to UNBOXED. */
1305         long remaining_bytes;
1306         page_index_t next_page;
1307         long bytes_freed;
1308         long old_bytes_used;
1309
1310         gc_assert(page_table[first_page].first_object_offset == 0);
1311
1312         next_page = first_page;
1313         remaining_bytes = nwords*N_WORD_BYTES;
1314         while (remaining_bytes > PAGE_BYTES) {
1315             gc_assert(page_table[next_page].gen == from_space);
1316             gc_assert((page_table[next_page].allocated == UNBOXED_PAGE_FLAG)
1317                       || (page_table[next_page].allocated == BOXED_PAGE_FLAG));
1318             gc_assert(page_table[next_page].large_object);
1319             gc_assert(page_table[next_page].first_object_offset==
1320                       -PAGE_BYTES*(next_page-first_page));
1321             gc_assert(page_table[next_page].bytes_used == PAGE_BYTES);
1322
1323             page_table[next_page].gen = new_space;
1324             page_table[next_page].allocated = UNBOXED_PAGE_FLAG;
1325             remaining_bytes -= PAGE_BYTES;
1326             next_page++;
1327         }
1328
1329         /* Now only one page remains, but the object may have shrunk so
1330          * there may be more unused pages which will be freed. */
1331
1332         /* Object may have shrunk but shouldn't have grown - check. */
1333         gc_assert(page_table[next_page].bytes_used >= remaining_bytes);
1334
1335         page_table[next_page].gen = new_space;
1336         page_table[next_page].allocated = UNBOXED_PAGE_FLAG;
1337
1338         /* Adjust the bytes_used. */
1339         old_bytes_used = page_table[next_page].bytes_used;
1340         page_table[next_page].bytes_used = remaining_bytes;
1341
1342         bytes_freed = old_bytes_used - remaining_bytes;
1343
1344         /* Free any remaining pages; needs care. */
1345         next_page++;
1346         while ((old_bytes_used == PAGE_BYTES) &&
1347                (page_table[next_page].gen == from_space) &&
1348                ((page_table[next_page].allocated == UNBOXED_PAGE_FLAG)
1349                 || (page_table[next_page].allocated == BOXED_PAGE_FLAG)) &&
1350                page_table[next_page].large_object &&
1351                (page_table[next_page].first_object_offset ==
1352                 -(next_page - first_page)*PAGE_BYTES)) {
1353             /* Checks out OK, free the page. Don't need to both zeroing
1354              * pages as this should have been done before shrinking the
1355              * object. These pages shouldn't be write-protected, even if
1356              * boxed they should be zero filled. */
1357             gc_assert(page_table[next_page].write_protected == 0);
1358
1359             old_bytes_used = page_table[next_page].bytes_used;
1360             page_table[next_page].allocated = FREE_PAGE_FLAG;
1361             page_table[next_page].bytes_used = 0;
1362             bytes_freed += old_bytes_used;
1363             next_page++;
1364         }
1365
1366         if ((bytes_freed > 0) && gencgc_verbose)
1367             FSHOW((stderr,
1368                    "/copy_large_unboxed bytes_freed=%d\n",
1369                    bytes_freed));
1370
1371         generations[from_space].bytes_allocated -= nwords*N_WORD_BYTES + bytes_freed;
1372         generations[new_space].bytes_allocated += nwords*N_WORD_BYTES;
1373         bytes_allocated -= bytes_freed;
1374
1375         return(object);
1376     }
1377     else {
1378         /* Get tag of object. */
1379         tag = lowtag_of(object);
1380
1381         /* Allocate space. */
1382         new = gc_quick_alloc_large_unboxed(nwords*N_WORD_BYTES);
1383
1384         /* Copy the object. */
1385         memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
1386
1387         /* Return Lisp pointer of new object. */
1388         return ((lispobj) new) | tag;
1389     }
1390 }
1391
1392
1393
1394 \f
1395
1396 /*
1397  * code and code-related objects
1398  */
1399 /*
1400 static lispobj trans_fun_header(lispobj object);
1401 static lispobj trans_boxed(lispobj object);
1402 */
1403
1404 /* Scan a x86 compiled code object, looking for possible fixups that
1405  * have been missed after a move.
1406  *
1407  * Two types of fixups are needed:
1408  * 1. Absolute fixups to within the code object.
1409  * 2. Relative fixups to outside the code object.
1410  *
1411  * Currently only absolute fixups to the constant vector, or to the
1412  * code area are checked. */
1413 void
1414 sniff_code_object(struct code *code, unsigned long displacement)
1415 {
1416     long nheader_words, ncode_words, nwords;
1417     void *p;
1418     void *constants_start_addr = NULL, *constants_end_addr;
1419     void *code_start_addr, *code_end_addr;
1420     int fixup_found = 0;
1421
1422     if (!check_code_fixups)
1423         return;
1424
1425     ncode_words = fixnum_value(code->code_size);
1426     nheader_words = HeaderValue(*(lispobj *)code);
1427     nwords = ncode_words + nheader_words;
1428
1429     constants_start_addr = (void *)code + 5*N_WORD_BYTES;
1430     constants_end_addr = (void *)code + nheader_words*N_WORD_BYTES;
1431     code_start_addr = (void *)code + nheader_words*N_WORD_BYTES;
1432     code_end_addr = (void *)code + nwords*N_WORD_BYTES;
1433
1434     /* Work through the unboxed code. */
1435     for (p = code_start_addr; p < code_end_addr; p++) {
1436         void *data = *(void **)p;
1437         unsigned d1 = *((unsigned char *)p - 1);
1438         unsigned d2 = *((unsigned char *)p - 2);
1439         unsigned d3 = *((unsigned char *)p - 3);
1440         unsigned d4 = *((unsigned char *)p - 4);
1441 #ifdef QSHOW
1442         unsigned d5 = *((unsigned char *)p - 5);
1443         unsigned d6 = *((unsigned char *)p - 6);
1444 #endif
1445
1446         /* Check for code references. */
1447         /* Check for a 32 bit word that looks like an absolute
1448            reference to within the code adea of the code object. */
1449         if ((data >= (code_start_addr-displacement))
1450             && (data < (code_end_addr-displacement))) {
1451             /* function header */
1452             if ((d4 == 0x5e)
1453                 && (((unsigned)p - 4 - 4*HeaderValue(*((unsigned *)p-1))) == (unsigned)code)) {
1454                 /* Skip the function header */
1455                 p += 6*4 - 4 - 1;
1456                 continue;
1457             }
1458             /* the case of PUSH imm32 */
1459             if (d1 == 0x68) {
1460                 fixup_found = 1;
1461                 FSHOW((stderr,
1462                        "/code ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1463                        p, d6, d5, d4, d3, d2, d1, data));
1464                 FSHOW((stderr, "/PUSH $0x%.8x\n", data));
1465             }
1466             /* the case of MOV [reg-8],imm32 */
1467             if ((d3 == 0xc7)
1468                 && (d2==0x40 || d2==0x41 || d2==0x42 || d2==0x43
1469                     || d2==0x45 || d2==0x46 || d2==0x47)
1470                 && (d1 == 0xf8)) {
1471                 fixup_found = 1;
1472                 FSHOW((stderr,
1473                        "/code ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1474                        p, d6, d5, d4, d3, d2, d1, data));
1475                 FSHOW((stderr, "/MOV [reg-8],$0x%.8x\n", data));
1476             }
1477             /* the case of LEA reg,[disp32] */
1478             if ((d2 == 0x8d) && ((d1 & 0xc7) == 5)) {
1479                 fixup_found = 1;
1480                 FSHOW((stderr,
1481                        "/code ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1482                        p, d6, d5, d4, d3, d2, d1, data));
1483                 FSHOW((stderr,"/LEA reg,[$0x%.8x]\n", data));
1484             }
1485         }
1486
1487         /* Check for constant references. */
1488         /* Check for a 32 bit word that looks like an absolute
1489            reference to within the constant vector. Constant references
1490            will be aligned. */
1491         if ((data >= (constants_start_addr-displacement))
1492             && (data < (constants_end_addr-displacement))
1493             && (((unsigned)data & 0x3) == 0)) {
1494             /*  Mov eax,m32 */
1495             if (d1 == 0xa1) {
1496                 fixup_found = 1;
1497                 FSHOW((stderr,
1498                        "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1499                        p, d6, d5, d4, d3, d2, d1, data));
1500                 FSHOW((stderr,"/MOV eax,0x%.8x\n", data));
1501             }
1502
1503             /*  the case of MOV m32,EAX */
1504             if (d1 == 0xa3) {
1505                 fixup_found = 1;
1506                 FSHOW((stderr,
1507                        "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1508                        p, d6, d5, d4, d3, d2, d1, data));
1509                 FSHOW((stderr, "/MOV 0x%.8x,eax\n", data));
1510             }
1511
1512             /* the case of CMP m32,imm32 */
1513             if ((d1 == 0x3d) && (d2 == 0x81)) {
1514                 fixup_found = 1;
1515                 FSHOW((stderr,
1516                        "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1517                        p, d6, d5, d4, d3, d2, d1, data));
1518                 /* XX Check this */
1519                 FSHOW((stderr, "/CMP 0x%.8x,immed32\n", data));
1520             }
1521
1522             /* Check for a mod=00, r/m=101 byte. */
1523             if ((d1 & 0xc7) == 5) {
1524                 /* Cmp m32,reg */
1525                 if (d2 == 0x39) {
1526                     fixup_found = 1;
1527                     FSHOW((stderr,
1528                            "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1529                            p, d6, d5, d4, d3, d2, d1, data));
1530                     FSHOW((stderr,"/CMP 0x%.8x,reg\n", data));
1531                 }
1532                 /* the case of CMP reg32,m32 */
1533                 if (d2 == 0x3b) {
1534                     fixup_found = 1;
1535                     FSHOW((stderr,
1536                            "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1537                            p, d6, d5, d4, d3, d2, d1, data));
1538                     FSHOW((stderr, "/CMP reg32,0x%.8x\n", data));
1539                 }
1540                 /* the case of MOV m32,reg32 */
1541                 if (d2 == 0x89) {
1542                     fixup_found = 1;
1543                     FSHOW((stderr,
1544                            "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1545                            p, d6, d5, d4, d3, d2, d1, data));
1546                     FSHOW((stderr, "/MOV 0x%.8x,reg32\n", data));
1547                 }
1548                 /* the case of MOV reg32,m32 */
1549                 if (d2 == 0x8b) {
1550                     fixup_found = 1;
1551                     FSHOW((stderr,
1552                            "/abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1553                            p, d6, d5, d4, d3, d2, d1, data));
1554                     FSHOW((stderr, "/MOV reg32,0x%.8x\n", data));
1555                 }
1556                 /* the case of LEA reg32,m32 */
1557                 if (d2 == 0x8d) {
1558                     fixup_found = 1;
1559                     FSHOW((stderr,
1560                            "abs const ref @%x: %.2x %.2x %.2x %.2x %.2x %.2x (%.8x)\n",
1561                            p, d6, d5, d4, d3, d2, d1, data));
1562                     FSHOW((stderr, "/LEA reg32,0x%.8x\n", data));
1563                 }
1564             }
1565         }
1566     }
1567
1568     /* If anything was found, print some information on the code
1569      * object. */
1570     if (fixup_found) {
1571         FSHOW((stderr,
1572                "/compiled code object at %x: header words = %d, code words = %d\n",
1573                code, nheader_words, ncode_words));
1574         FSHOW((stderr,
1575                "/const start = %x, end = %x\n",
1576                constants_start_addr, constants_end_addr));
1577         FSHOW((stderr,
1578                "/code start = %x, end = %x\n",
1579                code_start_addr, code_end_addr));
1580     }
1581 }
1582
1583 void
1584 gencgc_apply_code_fixups(struct code *old_code, struct code *new_code)
1585 {
1586     long nheader_words, ncode_words, nwords;
1587     void *constants_start_addr, *constants_end_addr;
1588     void *code_start_addr, *code_end_addr;
1589     lispobj fixups = NIL;
1590     unsigned long displacement = (unsigned long)new_code - (unsigned long)old_code;
1591     struct vector *fixups_vector;
1592
1593     ncode_words = fixnum_value(new_code->code_size);
1594     nheader_words = HeaderValue(*(lispobj *)new_code);
1595     nwords = ncode_words + nheader_words;
1596     /* FSHOW((stderr,
1597              "/compiled code object at %x: header words = %d, code words = %d\n",
1598              new_code, nheader_words, ncode_words)); */
1599     constants_start_addr = (void *)new_code + 5*N_WORD_BYTES;
1600     constants_end_addr = (void *)new_code + nheader_words*N_WORD_BYTES;
1601     code_start_addr = (void *)new_code + nheader_words*N_WORD_BYTES;
1602     code_end_addr = (void *)new_code + nwords*N_WORD_BYTES;
1603     /*
1604     FSHOW((stderr,
1605            "/const start = %x, end = %x\n",
1606            constants_start_addr,constants_end_addr));
1607     FSHOW((stderr,
1608            "/code start = %x; end = %x\n",
1609            code_start_addr,code_end_addr));
1610     */
1611
1612     /* The first constant should be a pointer to the fixups for this
1613        code objects. Check. */
1614     fixups = new_code->constants[0];
1615
1616     /* It will be 0 or the unbound-marker if there are no fixups (as
1617      * will be the case if the code object has been purified, for
1618      * example) and will be an other pointer if it is valid. */
1619     if ((fixups == 0) || (fixups == UNBOUND_MARKER_WIDETAG) ||
1620         !is_lisp_pointer(fixups)) {
1621         /* Check for possible errors. */
1622         if (check_code_fixups)
1623             sniff_code_object(new_code, displacement);
1624
1625         return;
1626     }
1627
1628     fixups_vector = (struct vector *)native_pointer(fixups);
1629
1630     /* Could be pointing to a forwarding pointer. */
1631     /* FIXME is this always in from_space?  if so, could replace this code with
1632      * forwarding_pointer_p/forwarding_pointer_value */
1633     if (is_lisp_pointer(fixups) &&
1634         (find_page_index((void*)fixups_vector) != -1) &&
1635         (fixups_vector->header == 0x01)) {
1636         /* If so, then follow it. */
1637         /*SHOW("following pointer to a forwarding pointer");*/
1638         fixups_vector = (struct vector *)native_pointer((lispobj)fixups_vector->length);
1639     }
1640
1641     /*SHOW("got fixups");*/
1642
1643     if (widetag_of(fixups_vector->header) == SIMPLE_ARRAY_WORD_WIDETAG) {
1644         /* Got the fixups for the code block. Now work through the vector,
1645            and apply a fixup at each address. */
1646         long length = fixnum_value(fixups_vector->length);
1647         long i;
1648         for (i = 0; i < length; i++) {
1649             unsigned long offset = fixups_vector->data[i];
1650             /* Now check the current value of offset. */
1651             unsigned long old_value =
1652                 *(unsigned long *)((unsigned long)code_start_addr + offset);
1653
1654             /* If it's within the old_code object then it must be an
1655              * absolute fixup (relative ones are not saved) */
1656             if ((old_value >= (unsigned long)old_code)
1657                 && (old_value < ((unsigned long)old_code + nwords*N_WORD_BYTES)))
1658                 /* So add the dispacement. */
1659                 *(unsigned long *)((unsigned long)code_start_addr + offset) =
1660                     old_value + displacement;
1661             else
1662                 /* It is outside the old code object so it must be a
1663                  * relative fixup (absolute fixups are not saved). So
1664                  * subtract the displacement. */
1665                 *(unsigned long *)((unsigned long)code_start_addr + offset) =
1666                     old_value - displacement;
1667         }
1668     } else {
1669         fprintf(stderr, "widetag of fixup vector is %d\n", widetag_of(fixups_vector->header));
1670     }
1671
1672     /* Check for possible errors. */
1673     if (check_code_fixups) {
1674         sniff_code_object(new_code,displacement);
1675     }
1676 }
1677
1678
1679 static lispobj
1680 trans_boxed_large(lispobj object)
1681 {
1682     lispobj header;
1683     unsigned long length;
1684
1685     gc_assert(is_lisp_pointer(object));
1686
1687     header = *((lispobj *) native_pointer(object));
1688     length = HeaderValue(header) + 1;
1689     length = CEILING(length, 2);
1690
1691     return copy_large_object(object, length);
1692 }
1693
1694 /* Doesn't seem to be used, delete it after the grace period. */
1695 #if 0
1696 static lispobj
1697 trans_unboxed_large(lispobj object)
1698 {
1699     lispobj header;
1700     unsigned long length;
1701
1702
1703     gc_assert(is_lisp_pointer(object));
1704
1705     header = *((lispobj *) native_pointer(object));
1706     length = HeaderValue(header) + 1;
1707     length = CEILING(length, 2);
1708
1709     return copy_large_unboxed_object(object, length);
1710 }
1711 #endif
1712
1713 \f
1714 /*
1715  * vector-like objects
1716  */
1717
1718
1719 /* FIXME: What does this mean? */
1720 int gencgc_hash = 1;
1721
1722 static long
1723 scav_vector(lispobj *where, lispobj object)
1724 {
1725     unsigned long kv_length;
1726     lispobj *kv_vector;
1727     unsigned long length = 0; /* (0 = dummy to stop GCC warning) */
1728     struct hash_table *hash_table;
1729     lispobj empty_symbol;
1730     unsigned long *index_vector = NULL; /* (NULL = dummy to stop GCC warning) */
1731     unsigned long *next_vector = NULL; /* (NULL = dummy to stop GCC warning) */
1732     unsigned long *hash_vector = NULL; /* (NULL = dummy to stop GCC warning) */
1733     lispobj weak_p_obj;
1734     unsigned long next_vector_length = 0;
1735
1736     /* FIXME: A comment explaining this would be nice. It looks as
1737      * though SB-VM:VECTOR-VALID-HASHING-SUBTYPE is set for EQ-based
1738      * hash tables in the Lisp HASH-TABLE code, and nowhere else. */
1739     if (HeaderValue(object) != subtype_VectorValidHashing)
1740         return 1;
1741
1742     if (!gencgc_hash) {
1743         /* This is set for backward compatibility. FIXME: Do we need
1744          * this any more? */
1745         *where =
1746             (subtype_VectorMustRehash<<N_WIDETAG_BITS) | SIMPLE_VECTOR_WIDETAG;
1747         return 1;
1748     }
1749
1750     kv_length = fixnum_value(where[1]);
1751     kv_vector = where + 2;  /* Skip the header and length. */
1752     /*FSHOW((stderr,"/kv_length = %d\n", kv_length));*/
1753
1754     /* Scavenge element 0, which may be a hash-table structure. */
1755     scavenge(where+2, 1);
1756     if (!is_lisp_pointer(where[2])) {
1757         lose("no pointer at %x in hash table", where[2]);
1758     }
1759     hash_table = (struct hash_table *)native_pointer(where[2]);
1760     /*FSHOW((stderr,"/hash_table = %x\n", hash_table));*/
1761     if (widetag_of(hash_table->header) != INSTANCE_HEADER_WIDETAG) {
1762         lose("hash table not instance (%x at %x)",
1763              hash_table->header,
1764              hash_table);
1765     }
1766
1767     /* Scavenge element 1, which should be some internal symbol that
1768      * the hash table code reserves for marking empty slots. */
1769     scavenge(where+3, 1);
1770     if (!is_lisp_pointer(where[3])) {
1771         lose("not empty-hash-table-slot symbol pointer: %x", where[3]);
1772     }
1773     empty_symbol = where[3];
1774     /* fprintf(stderr,"* empty_symbol = %x\n", empty_symbol);*/
1775     if (widetag_of(*(lispobj *)native_pointer(empty_symbol)) !=
1776         SYMBOL_HEADER_WIDETAG) {
1777         lose("not a symbol where empty-hash-table-slot symbol expected: %x",
1778              *(lispobj *)native_pointer(empty_symbol));
1779     }
1780
1781     /* Scavenge hash table, which will fix the positions of the other
1782      * needed objects. */
1783     scavenge((lispobj *)hash_table,
1784              sizeof(struct hash_table) / sizeof(lispobj));
1785
1786     /* Cross-check the kv_vector. */
1787     if (where != (lispobj *)native_pointer(hash_table->table)) {
1788         lose("hash_table table!=this table %x", hash_table->table);
1789     }
1790
1791     /* WEAK-P */
1792     weak_p_obj = hash_table->weak_p;
1793
1794     /* index vector */
1795     {
1796         lispobj index_vector_obj = hash_table->index_vector;
1797
1798         if (is_lisp_pointer(index_vector_obj) &&
1799             (widetag_of(*(lispobj *)native_pointer(index_vector_obj)) ==
1800                  SIMPLE_ARRAY_WORD_WIDETAG)) {
1801             index_vector =
1802                 ((unsigned long *)native_pointer(index_vector_obj)) + 2;
1803             /*FSHOW((stderr, "/index_vector = %x\n",index_vector));*/
1804             length = fixnum_value(((lispobj *)native_pointer(index_vector_obj))[1]);
1805             /*FSHOW((stderr, "/length = %d\n", length));*/
1806         } else {
1807             lose("invalid index_vector %x", index_vector_obj);
1808         }
1809     }
1810
1811     /* next vector */
1812     {
1813         lispobj next_vector_obj = hash_table->next_vector;
1814
1815         if (is_lisp_pointer(next_vector_obj) &&
1816             (widetag_of(*(lispobj *)native_pointer(next_vector_obj)) ==
1817              SIMPLE_ARRAY_WORD_WIDETAG)) {
1818             next_vector = ((unsigned long *)native_pointer(next_vector_obj)) + 2;
1819             /*FSHOW((stderr, "/next_vector = %x\n", next_vector));*/
1820             next_vector_length = fixnum_value(((lispobj *)native_pointer(next_vector_obj))[1]);
1821             /*FSHOW((stderr, "/next_vector_length = %d\n", next_vector_length));*/
1822         } else {
1823             lose("invalid next_vector %x", next_vector_obj);
1824         }
1825     }
1826
1827     /* maybe hash vector */
1828     {
1829         lispobj hash_vector_obj = hash_table->hash_vector;
1830
1831         if (is_lisp_pointer(hash_vector_obj) &&
1832             (widetag_of(*(lispobj *)native_pointer(hash_vector_obj)) ==
1833              SIMPLE_ARRAY_WORD_WIDETAG)){
1834             hash_vector =
1835                 ((unsigned long *)native_pointer(hash_vector_obj)) + 2;
1836             /*FSHOW((stderr, "/hash_vector = %x\n", hash_vector));*/
1837             gc_assert(fixnum_value(((lispobj *)native_pointer(hash_vector_obj))[1])
1838                       == next_vector_length);
1839         } else {
1840             hash_vector = NULL;
1841             /*FSHOW((stderr, "/no hash_vector: %x\n", hash_vector_obj));*/
1842         }
1843     }
1844
1845     /* These lengths could be different as the index_vector can be a
1846      * different length from the others, a larger index_vector could help
1847      * reduce collisions. */
1848     gc_assert(next_vector_length*2 == kv_length);
1849
1850     /* now all set up.. */
1851
1852     /* Work through the KV vector. */
1853     {
1854         long i;
1855         for (i = 1; i < next_vector_length; i++) {
1856             lispobj old_key = kv_vector[2*i];
1857
1858 #if N_WORD_BITS == 32
1859             unsigned long old_index = (old_key & 0x1fffffff)%length;
1860 #elif N_WORD_BITS == 64
1861             unsigned long old_index = (old_key & 0x1fffffffffffffff)%length;
1862 #endif
1863
1864             /* Scavenge the key and value. */
1865             scavenge(&kv_vector[2*i],2);
1866
1867             /* Check whether the key has moved and is EQ based. */
1868             {
1869                 lispobj new_key = kv_vector[2*i];
1870 #if N_WORD_BITS == 32
1871                 unsigned long new_index = (new_key & 0x1fffffff)%length;
1872 #elif N_WORD_BITS == 64
1873                 unsigned long new_index = (new_key & 0x1fffffffffffffff)%length;
1874 #endif
1875
1876                 if ((old_index != new_index) &&
1877                     ((!hash_vector) ||
1878                      (hash_vector[i] == MAGIC_HASH_VECTOR_VALUE)) &&
1879                     ((new_key != empty_symbol) ||
1880                      (kv_vector[2*i] != empty_symbol))) {
1881
1882                      /*FSHOW((stderr,
1883                             "* EQ key %d moved from %x to %x; index %d to %d\n",
1884                             i, old_key, new_key, old_index, new_index));*/
1885
1886                     if (index_vector[old_index] != 0) {
1887                          /*FSHOW((stderr, "/P1 %d\n", index_vector[old_index]));*/
1888
1889                         /* Unlink the key from the old_index chain. */
1890                         if (index_vector[old_index] == i) {
1891                             /*FSHOW((stderr, "/P2a %d\n", next_vector[i]));*/
1892                             index_vector[old_index] = next_vector[i];
1893                             /* Link it into the needing rehash chain. */
1894                             next_vector[i] = fixnum_value(hash_table->needing_rehash);
1895                             hash_table->needing_rehash = make_fixnum(i);
1896                             /*SHOW("P2");*/
1897                         } else {
1898                             unsigned long prior = index_vector[old_index];
1899                             unsigned long next = next_vector[prior];
1900
1901                             /*FSHOW((stderr, "/P3a %d %d\n", prior, next));*/
1902
1903                             while (next != 0) {
1904                                  /*FSHOW((stderr, "/P3b %d %d\n", prior, next));*/
1905                                 if (next == i) {
1906                                     /* Unlink it. */
1907                                     next_vector[prior] = next_vector[next];
1908                                     /* Link it into the needing rehash
1909                                      * chain. */
1910                                     next_vector[next] =
1911                                         fixnum_value(hash_table->needing_rehash);
1912                                     hash_table->needing_rehash = make_fixnum(next);
1913                                     /*SHOW("/P3");*/
1914                                     break;
1915                                 }
1916                                 prior = next;
1917                                 next = next_vector[next];
1918                             }
1919                         }
1920                     }
1921                 }
1922             }
1923         }
1924     }
1925     return (CEILING(kv_length + 2, 2));
1926 }
1927
1928
1929 \f
1930 /*
1931  * weak pointers
1932  */
1933
1934 /* XX This is a hack adapted from cgc.c. These don't work too
1935  * efficiently with the gencgc as a list of the weak pointers is
1936  * maintained within the objects which causes writes to the pages. A
1937  * limited attempt is made to avoid unnecessary writes, but this needs
1938  * a re-think. */
1939 #define WEAK_POINTER_NWORDS \
1940     CEILING((sizeof(struct weak_pointer) / sizeof(lispobj)), 2)
1941
1942 static long
1943 scav_weak_pointer(lispobj *where, lispobj object)
1944 {
1945     struct weak_pointer *wp = weak_pointers;
1946     /* Push the weak pointer onto the list of weak pointers.
1947      * Do I have to watch for duplicates? Originally this was
1948      * part of trans_weak_pointer but that didn't work in the
1949      * case where the WP was in a promoted region.
1950      */
1951
1952     /* Check whether it's already in the list. */
1953     while (wp != NULL) {
1954         if (wp == (struct weak_pointer*)where) {
1955             break;
1956         }
1957         wp = wp->next;
1958     }
1959     if (wp == NULL) {
1960         /* Add it to the start of the list. */
1961         wp = (struct weak_pointer*)where;
1962         if (wp->next != weak_pointers) {
1963             wp->next = weak_pointers;
1964         } else {
1965             /*SHOW("avoided write to weak pointer");*/
1966         }
1967         weak_pointers = wp;
1968     }
1969
1970     /* Do not let GC scavenge the value slot of the weak pointer.
1971      * (That is why it is a weak pointer.) */
1972
1973     return WEAK_POINTER_NWORDS;
1974 }
1975
1976 \f
1977 lispobj *
1978 search_read_only_space(void *pointer)
1979 {
1980     lispobj *start = (lispobj *) READ_ONLY_SPACE_START;
1981     lispobj *end = (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0);
1982     if ((pointer < (void *)start) || (pointer >= (void *)end))
1983         return NULL;
1984     return (gc_search_space(start,
1985                             (((lispobj *)pointer)+2)-start,
1986                             (lispobj *) pointer));
1987 }
1988
1989 lispobj *
1990 search_static_space(void *pointer)
1991 {
1992     lispobj *start = (lispobj *)STATIC_SPACE_START;
1993     lispobj *end = (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0);
1994     if ((pointer < (void *)start) || (pointer >= (void *)end))
1995         return NULL;
1996     return (gc_search_space(start,
1997                             (((lispobj *)pointer)+2)-start,
1998                             (lispobj *) pointer));
1999 }
2000
2001 /* a faster version for searching the dynamic space. This will work even
2002  * if the object is in a current allocation region. */
2003 lispobj *
2004 search_dynamic_space(void *pointer)
2005 {
2006     page_index_t page_index = find_page_index(pointer);
2007     lispobj *start;
2008
2009     /* The address may be invalid, so do some checks. */
2010     if ((page_index == -1) ||
2011         (page_table[page_index].allocated == FREE_PAGE_FLAG))
2012         return NULL;
2013     start = (lispobj *)((void *)page_address(page_index)
2014                         + page_table[page_index].first_object_offset);
2015     return (gc_search_space(start,
2016                             (((lispobj *)pointer)+2)-start,
2017                             (lispobj *)pointer));
2018 }
2019
2020 /* Is there any possibility that pointer is a valid Lisp object
2021  * reference, and/or something else (e.g. subroutine call return
2022  * address) which should prevent us from moving the referred-to thing?
2023  * This is called from preserve_pointers() */
2024 static int
2025 possibly_valid_dynamic_space_pointer(lispobj *pointer)
2026 {
2027     lispobj *start_addr;
2028
2029     /* Find the object start address. */
2030     if ((start_addr = search_dynamic_space(pointer)) == NULL) {
2031         return 0;
2032     }
2033
2034     /* We need to allow raw pointers into Code objects for return
2035      * addresses. This will also pick up pointers to functions in code
2036      * objects. */
2037     if (widetag_of(*start_addr) == CODE_HEADER_WIDETAG) {
2038         /* XXX could do some further checks here */
2039         return 1;
2040     }
2041
2042     /* If it's not a return address then it needs to be a valid Lisp
2043      * pointer. */
2044     if (!is_lisp_pointer((lispobj)pointer)) {
2045         return 0;
2046     }
2047
2048     /* Check that the object pointed to is consistent with the pointer
2049      * low tag.
2050      */
2051     switch (lowtag_of((lispobj)pointer)) {
2052     case FUN_POINTER_LOWTAG:
2053         /* Start_addr should be the enclosing code object, or a closure
2054          * header. */
2055         switch (widetag_of(*start_addr)) {
2056         case CODE_HEADER_WIDETAG:
2057             /* This case is probably caught above. */
2058             break;
2059         case CLOSURE_HEADER_WIDETAG:
2060         case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
2061             if ((unsigned long)pointer !=
2062                 ((unsigned long)start_addr+FUN_POINTER_LOWTAG)) {
2063                 if (gencgc_verbose)
2064                     FSHOW((stderr,
2065                            "/Wf2: %x %x %x\n",
2066                            pointer, start_addr, *start_addr));
2067                 return 0;
2068             }
2069             break;
2070         default:
2071             if (gencgc_verbose)
2072                 FSHOW((stderr,
2073                        "/Wf3: %x %x %x\n",
2074                        pointer, start_addr, *start_addr));
2075             return 0;
2076         }
2077         break;
2078     case LIST_POINTER_LOWTAG:
2079         if ((unsigned long)pointer !=
2080             ((unsigned long)start_addr+LIST_POINTER_LOWTAG)) {
2081             if (gencgc_verbose)
2082                 FSHOW((stderr,
2083                        "/Wl1: %x %x %x\n",
2084                        pointer, start_addr, *start_addr));
2085             return 0;
2086         }
2087         /* Is it plausible cons? */
2088         if ((is_lisp_pointer(start_addr[0])
2089             || (fixnump(start_addr[0]))
2090             || (widetag_of(start_addr[0]) == CHARACTER_WIDETAG)
2091 #if N_WORD_BITS == 64
2092             || (widetag_of(start_addr[0]) == SINGLE_FLOAT_WIDETAG)
2093 #endif
2094             || (widetag_of(start_addr[0]) == UNBOUND_MARKER_WIDETAG))
2095            && (is_lisp_pointer(start_addr[1])
2096                || (fixnump(start_addr[1]))
2097                || (widetag_of(start_addr[1]) == CHARACTER_WIDETAG)
2098 #if N_WORD_BITS == 64
2099                || (widetag_of(start_addr[1]) == SINGLE_FLOAT_WIDETAG)
2100 #endif
2101                || (widetag_of(start_addr[1]) == UNBOUND_MARKER_WIDETAG)))
2102             break;
2103         else {
2104             if (gencgc_verbose)
2105                 FSHOW((stderr,
2106                        "/Wl2: %x %x %x\n",
2107                        pointer, start_addr, *start_addr));
2108             return 0;
2109         }
2110     case INSTANCE_POINTER_LOWTAG:
2111         if ((unsigned long)pointer !=
2112             ((unsigned long)start_addr+INSTANCE_POINTER_LOWTAG)) {
2113             if (gencgc_verbose)
2114                 FSHOW((stderr,
2115                        "/Wi1: %x %x %x\n",
2116                        pointer, start_addr, *start_addr));
2117             return 0;
2118         }
2119         if (widetag_of(start_addr[0]) != INSTANCE_HEADER_WIDETAG) {
2120             if (gencgc_verbose)
2121                 FSHOW((stderr,
2122                        "/Wi2: %x %x %x\n",
2123                        pointer, start_addr, *start_addr));
2124             return 0;
2125         }
2126         break;
2127     case OTHER_POINTER_LOWTAG:
2128         if ((unsigned long)pointer !=
2129             ((unsigned long)start_addr+OTHER_POINTER_LOWTAG)) {
2130             if (gencgc_verbose)
2131                 FSHOW((stderr,
2132                        "/Wo1: %x %x %x\n",
2133                        pointer, start_addr, *start_addr));
2134             return 0;
2135         }
2136         /* Is it plausible?  Not a cons. XXX should check the headers. */
2137         if (is_lisp_pointer(start_addr[0]) || ((start_addr[0] & 3) == 0)) {
2138             if (gencgc_verbose)
2139                 FSHOW((stderr,
2140                        "/Wo2: %x %x %x\n",
2141                        pointer, start_addr, *start_addr));
2142             return 0;
2143         }
2144         switch (widetag_of(start_addr[0])) {
2145         case UNBOUND_MARKER_WIDETAG:
2146         case NO_TLS_VALUE_MARKER_WIDETAG:
2147         case CHARACTER_WIDETAG:
2148 #if N_WORD_BITS == 64
2149         case SINGLE_FLOAT_WIDETAG:
2150 #endif
2151             if (gencgc_verbose)
2152                 FSHOW((stderr,
2153                        "*Wo3: %x %x %x\n",
2154                        pointer, start_addr, *start_addr));
2155             return 0;
2156
2157             /* only pointed to by function pointers? */
2158         case CLOSURE_HEADER_WIDETAG:
2159         case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
2160             if (gencgc_verbose)
2161                 FSHOW((stderr,
2162                        "*Wo4: %x %x %x\n",
2163                        pointer, start_addr, *start_addr));
2164             return 0;
2165
2166         case INSTANCE_HEADER_WIDETAG:
2167             if (gencgc_verbose)
2168                 FSHOW((stderr,
2169                        "*Wo5: %x %x %x\n",
2170                        pointer, start_addr, *start_addr));
2171             return 0;
2172
2173             /* the valid other immediate pointer objects */
2174         case SIMPLE_VECTOR_WIDETAG:
2175         case RATIO_WIDETAG:
2176         case COMPLEX_WIDETAG:
2177 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
2178         case COMPLEX_SINGLE_FLOAT_WIDETAG:
2179 #endif
2180 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
2181         case COMPLEX_DOUBLE_FLOAT_WIDETAG:
2182 #endif
2183 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
2184         case COMPLEX_LONG_FLOAT_WIDETAG:
2185 #endif
2186         case SIMPLE_ARRAY_WIDETAG:
2187         case COMPLEX_BASE_STRING_WIDETAG:
2188 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
2189         case COMPLEX_CHARACTER_STRING_WIDETAG:
2190 #endif
2191         case COMPLEX_VECTOR_NIL_WIDETAG:
2192         case COMPLEX_BIT_VECTOR_WIDETAG:
2193         case COMPLEX_VECTOR_WIDETAG:
2194         case COMPLEX_ARRAY_WIDETAG:
2195         case VALUE_CELL_HEADER_WIDETAG:
2196         case SYMBOL_HEADER_WIDETAG:
2197         case FDEFN_WIDETAG:
2198         case CODE_HEADER_WIDETAG:
2199         case BIGNUM_WIDETAG:
2200 #if N_WORD_BITS != 64
2201         case SINGLE_FLOAT_WIDETAG:
2202 #endif
2203         case DOUBLE_FLOAT_WIDETAG:
2204 #ifdef LONG_FLOAT_WIDETAG
2205         case LONG_FLOAT_WIDETAG:
2206 #endif
2207         case SIMPLE_BASE_STRING_WIDETAG:
2208 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
2209         case SIMPLE_CHARACTER_STRING_WIDETAG:
2210 #endif
2211         case SIMPLE_BIT_VECTOR_WIDETAG:
2212         case SIMPLE_ARRAY_NIL_WIDETAG:
2213         case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
2214         case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
2215         case SIMPLE_ARRAY_UNSIGNED_BYTE_7_WIDETAG:
2216         case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
2217         case SIMPLE_ARRAY_UNSIGNED_BYTE_15_WIDETAG:
2218         case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
2219 #ifdef  SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG
2220         case SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG:
2221 #endif
2222         case SIMPLE_ARRAY_UNSIGNED_BYTE_31_WIDETAG:
2223         case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
2224 #ifdef  SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG
2225         case SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG:
2226 #endif
2227 #ifdef  SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG
2228         case SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG:
2229 #endif
2230 #ifdef  SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG
2231         case SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG:
2232 #endif
2233 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
2234         case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
2235 #endif
2236 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
2237         case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
2238 #endif
2239 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
2240         case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
2241 #endif
2242 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
2243         case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
2244 #endif
2245 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_61_WIDETAG
2246         case SIMPLE_ARRAY_SIGNED_BYTE_61_WIDETAG:
2247 #endif
2248 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG
2249         case SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG:
2250 #endif
2251         case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
2252         case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
2253 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
2254         case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
2255 #endif
2256 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
2257         case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
2258 #endif
2259 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
2260         case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
2261 #endif
2262 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
2263         case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
2264 #endif
2265         case SAP_WIDETAG:
2266         case WEAK_POINTER_WIDETAG:
2267             break;
2268
2269         default:
2270             if (gencgc_verbose)
2271                 FSHOW((stderr,
2272                        "/Wo6: %x %x %x\n",
2273                        pointer, start_addr, *start_addr));
2274             return 0;
2275         }
2276         break;
2277     default:
2278         if (gencgc_verbose)
2279             FSHOW((stderr,
2280                    "*W?: %x %x %x\n",
2281                    pointer, start_addr, *start_addr));
2282         return 0;
2283     }
2284
2285     /* looks good */
2286     return 1;
2287 }
2288
2289 /* Adjust large bignum and vector objects. This will adjust the
2290  * allocated region if the size has shrunk, and move unboxed objects
2291  * into unboxed pages. The pages are not promoted here, and the
2292  * promoted region is not added to the new_regions; this is really
2293  * only designed to be called from preserve_pointer(). Shouldn't fail
2294  * if this is missed, just may delay the moving of objects to unboxed
2295  * pages, and the freeing of pages. */
2296 static void
2297 maybe_adjust_large_object(lispobj *where)
2298 {
2299     page_index_t first_page;
2300     page_index_t next_page;
2301     long nwords;
2302
2303     long remaining_bytes;
2304     long bytes_freed;
2305     long old_bytes_used;
2306
2307     int boxed;
2308
2309     /* Check whether it's a vector or bignum object. */
2310     switch (widetag_of(where[0])) {
2311     case SIMPLE_VECTOR_WIDETAG:
2312         boxed = BOXED_PAGE_FLAG;
2313         break;
2314     case BIGNUM_WIDETAG:
2315     case SIMPLE_BASE_STRING_WIDETAG:
2316 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
2317     case SIMPLE_CHARACTER_STRING_WIDETAG:
2318 #endif
2319     case SIMPLE_BIT_VECTOR_WIDETAG:
2320     case SIMPLE_ARRAY_NIL_WIDETAG:
2321     case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
2322     case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
2323     case SIMPLE_ARRAY_UNSIGNED_BYTE_7_WIDETAG:
2324     case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
2325     case SIMPLE_ARRAY_UNSIGNED_BYTE_15_WIDETAG:
2326     case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
2327 #ifdef  SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG
2328     case SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG:
2329 #endif
2330     case SIMPLE_ARRAY_UNSIGNED_BYTE_31_WIDETAG:
2331     case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
2332 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG
2333     case SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG:
2334 #endif
2335 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG
2336     case SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG:
2337 #endif
2338 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG
2339     case SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG:
2340 #endif
2341 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
2342     case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
2343 #endif
2344 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
2345     case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
2346 #endif
2347 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
2348     case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
2349 #endif
2350 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
2351     case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
2352 #endif
2353 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_61_WIDETAG
2354     case SIMPLE_ARRAY_SIGNED_BYTE_61_WIDETAG:
2355 #endif
2356 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG
2357     case SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG:
2358 #endif
2359     case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
2360     case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
2361 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
2362     case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
2363 #endif
2364 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
2365     case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
2366 #endif
2367 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
2368     case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
2369 #endif
2370 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
2371     case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
2372 #endif
2373         boxed = UNBOXED_PAGE_FLAG;
2374         break;
2375     default:
2376         return;
2377     }
2378
2379     /* Find its current size. */
2380     nwords = (sizetab[widetag_of(where[0])])(where);
2381
2382     first_page = find_page_index((void *)where);
2383     gc_assert(first_page >= 0);
2384
2385     /* Note: Any page write-protection must be removed, else a later
2386      * scavenge_newspace may incorrectly not scavenge these pages.
2387      * This would not be necessary if they are added to the new areas,
2388      * but lets do it for them all (they'll probably be written
2389      * anyway?). */
2390
2391     gc_assert(page_table[first_page].first_object_offset == 0);
2392
2393     next_page = first_page;
2394     remaining_bytes = nwords*N_WORD_BYTES;
2395     while (remaining_bytes > PAGE_BYTES) {
2396         gc_assert(page_table[next_page].gen == from_space);
2397         gc_assert((page_table[next_page].allocated == BOXED_PAGE_FLAG)
2398                   || (page_table[next_page].allocated == UNBOXED_PAGE_FLAG));
2399         gc_assert(page_table[next_page].large_object);
2400         gc_assert(page_table[next_page].first_object_offset ==
2401                   -PAGE_BYTES*(next_page-first_page));
2402         gc_assert(page_table[next_page].bytes_used == PAGE_BYTES);
2403
2404         page_table[next_page].allocated = boxed;
2405
2406         /* Shouldn't be write-protected at this stage. Essential that the
2407          * pages aren't. */
2408         gc_assert(!page_table[next_page].write_protected);
2409         remaining_bytes -= PAGE_BYTES;
2410         next_page++;
2411     }
2412
2413     /* Now only one page remains, but the object may have shrunk so
2414      * there may be more unused pages which will be freed. */
2415
2416     /* Object may have shrunk but shouldn't have grown - check. */
2417     gc_assert(page_table[next_page].bytes_used >= remaining_bytes);
2418
2419     page_table[next_page].allocated = boxed;
2420     gc_assert(page_table[next_page].allocated ==
2421               page_table[first_page].allocated);
2422
2423     /* Adjust the bytes_used. */
2424     old_bytes_used = page_table[next_page].bytes_used;
2425     page_table[next_page].bytes_used = remaining_bytes;
2426
2427     bytes_freed = old_bytes_used - remaining_bytes;
2428
2429     /* Free any remaining pages; needs care. */
2430     next_page++;
2431     while ((old_bytes_used == PAGE_BYTES) &&
2432            (page_table[next_page].gen == from_space) &&
2433            ((page_table[next_page].allocated == UNBOXED_PAGE_FLAG)
2434             || (page_table[next_page].allocated == BOXED_PAGE_FLAG)) &&
2435            page_table[next_page].large_object &&
2436            (page_table[next_page].first_object_offset ==
2437             -(next_page - first_page)*PAGE_BYTES)) {
2438         /* It checks out OK, free the page. We don't need to both zeroing
2439          * pages as this should have been done before shrinking the
2440          * object. These pages shouldn't be write protected as they
2441          * should be zero filled. */
2442         gc_assert(page_table[next_page].write_protected == 0);
2443
2444         old_bytes_used = page_table[next_page].bytes_used;
2445         page_table[next_page].allocated = FREE_PAGE_FLAG;
2446         page_table[next_page].bytes_used = 0;
2447         bytes_freed += old_bytes_used;
2448         next_page++;
2449     }
2450
2451     if ((bytes_freed > 0) && gencgc_verbose) {
2452         FSHOW((stderr,
2453                "/maybe_adjust_large_object() freed %d\n",
2454                bytes_freed));
2455     }
2456
2457     generations[from_space].bytes_allocated -= bytes_freed;
2458     bytes_allocated -= bytes_freed;
2459
2460     return;
2461 }
2462
2463 /* Take a possible pointer to a Lisp object and mark its page in the
2464  * page_table so that it will not be relocated during a GC.
2465  *
2466  * This involves locating the page it points to, then backing up to
2467  * the start of its region, then marking all pages dont_move from there
2468  * up to the first page that's not full or has a different generation
2469  *
2470  * It is assumed that all the page static flags have been cleared at
2471  * the start of a GC.
2472  *
2473  * It is also assumed that the current gc_alloc() region has been
2474  * flushed and the tables updated. */
2475 static void
2476 preserve_pointer(void *addr)
2477 {
2478     page_index_t addr_page_index = find_page_index(addr);
2479     page_index_t first_page;
2480     page_index_t i;
2481     unsigned int region_allocation;
2482
2483     /* quick check 1: Address is quite likely to have been invalid. */
2484     if ((addr_page_index == -1)
2485         || (page_table[addr_page_index].allocated == FREE_PAGE_FLAG)
2486         || (page_table[addr_page_index].bytes_used == 0)
2487         || (page_table[addr_page_index].gen != from_space)
2488         /* Skip if already marked dont_move. */
2489         || (page_table[addr_page_index].dont_move != 0))
2490         return;
2491     gc_assert(!(page_table[addr_page_index].allocated&OPEN_REGION_PAGE_FLAG));
2492     /* (Now that we know that addr_page_index is in range, it's
2493      * safe to index into page_table[] with it.) */
2494     region_allocation = page_table[addr_page_index].allocated;
2495
2496     /* quick check 2: Check the offset within the page.
2497      *
2498      */
2499     if (((unsigned long)addr & (PAGE_BYTES - 1)) > page_table[addr_page_index].bytes_used)
2500         return;
2501
2502     /* Filter out anything which can't be a pointer to a Lisp object
2503      * (or, as a special case which also requires dont_move, a return
2504      * address referring to something in a CodeObject). This is
2505      * expensive but important, since it vastly reduces the
2506      * probability that random garbage will be bogusly interpreted as
2507      * a pointer which prevents a page from moving. */
2508     if (!(possibly_valid_dynamic_space_pointer(addr)))
2509         return;
2510
2511     /* Find the beginning of the region.  Note that there may be
2512      * objects in the region preceding the one that we were passed a
2513      * pointer to: if this is the case, we will write-protect all the
2514      * previous objects' pages too.     */
2515
2516 #if 0
2517     /* I think this'd work just as well, but without the assertions.
2518      * -dan 2004.01.01 */
2519     first_page=
2520         find_page_index(page_address(addr_page_index)+
2521                         page_table[addr_page_index].first_object_offset);
2522 #else
2523     first_page = addr_page_index;
2524     while (page_table[first_page].first_object_offset != 0) {
2525         --first_page;
2526         /* Do some checks. */
2527         gc_assert(page_table[first_page].bytes_used == PAGE_BYTES);
2528         gc_assert(page_table[first_page].gen == from_space);
2529         gc_assert(page_table[first_page].allocated == region_allocation);
2530     }
2531 #endif
2532
2533     /* Adjust any large objects before promotion as they won't be
2534      * copied after promotion. */
2535     if (page_table[first_page].large_object) {
2536         maybe_adjust_large_object(page_address(first_page));
2537         /* If a large object has shrunk then addr may now point to a
2538          * free area in which case it's ignored here. Note it gets
2539          * through the valid pointer test above because the tail looks
2540          * like conses. */
2541         if ((page_table[addr_page_index].allocated == FREE_PAGE_FLAG)
2542             || (page_table[addr_page_index].bytes_used == 0)
2543             /* Check the offset within the page. */
2544             || (((unsigned long)addr & (PAGE_BYTES - 1))
2545                 > page_table[addr_page_index].bytes_used)) {
2546             FSHOW((stderr,
2547                    "weird? ignore ptr 0x%x to freed area of large object\n",
2548                    addr));
2549             return;
2550         }
2551         /* It may have moved to unboxed pages. */
2552         region_allocation = page_table[first_page].allocated;
2553     }
2554
2555     /* Now work forward until the end of this contiguous area is found,
2556      * marking all pages as dont_move. */
2557     for (i = first_page; ;i++) {
2558         gc_assert(page_table[i].allocated == region_allocation);
2559
2560         /* Mark the page static. */
2561         page_table[i].dont_move = 1;
2562
2563         /* Move the page to the new_space. XX I'd rather not do this
2564          * but the GC logic is not quite able to copy with the static
2565          * pages remaining in the from space. This also requires the
2566          * generation bytes_allocated counters be updated. */
2567         page_table[i].gen = new_space;
2568         generations[new_space].bytes_allocated += page_table[i].bytes_used;
2569         generations[from_space].bytes_allocated -= page_table[i].bytes_used;
2570
2571         /* It is essential that the pages are not write protected as
2572          * they may have pointers into the old-space which need
2573          * scavenging. They shouldn't be write protected at this
2574          * stage. */
2575         gc_assert(!page_table[i].write_protected);
2576
2577         /* Check whether this is the last page in this contiguous block.. */
2578         if ((page_table[i].bytes_used < PAGE_BYTES)
2579             /* ..or it is PAGE_BYTES and is the last in the block */
2580             || (page_table[i+1].allocated == FREE_PAGE_FLAG)
2581             || (page_table[i+1].bytes_used == 0) /* next page free */
2582             || (page_table[i+1].gen != from_space) /* diff. gen */
2583             || (page_table[i+1].first_object_offset == 0))
2584             break;
2585     }
2586
2587     /* Check that the page is now static. */
2588     gc_assert(page_table[addr_page_index].dont_move != 0);
2589 }
2590 \f
2591 /* If the given page is not write-protected, then scan it for pointers
2592  * to younger generations or the top temp. generation, if no
2593  * suspicious pointers are found then the page is write-protected.
2594  *
2595  * Care is taken to check for pointers to the current gc_alloc()
2596  * region if it is a younger generation or the temp. generation. This
2597  * frees the caller from doing a gc_alloc_update_page_tables(). Actually
2598  * the gc_alloc_generation does not need to be checked as this is only
2599  * called from scavenge_generation() when the gc_alloc generation is
2600  * younger, so it just checks if there is a pointer to the current
2601  * region.
2602  *
2603  * We return 1 if the page was write-protected, else 0. */
2604 static int
2605 update_page_write_prot(page_index_t page)
2606 {
2607     generation_index_t gen = page_table[page].gen;
2608     long j;
2609     int wp_it = 1;
2610     void **page_addr = (void **)page_address(page);
2611     long num_words = page_table[page].bytes_used / N_WORD_BYTES;
2612
2613     /* Shouldn't be a free page. */
2614     gc_assert(page_table[page].allocated != FREE_PAGE_FLAG);
2615     gc_assert(page_table[page].bytes_used != 0);
2616
2617     /* Skip if it's already write-protected, pinned, or unboxed */
2618     if (page_table[page].write_protected
2619         /* FIXME: What's the reason for not write-protecting pinned pages? */
2620         || page_table[page].dont_move
2621         || (page_table[page].allocated & UNBOXED_PAGE_FLAG))
2622         return (0);
2623
2624     /* Scan the page for pointers to younger generations or the
2625      * top temp. generation. */
2626
2627     for (j = 0; j < num_words; j++) {
2628         void *ptr = *(page_addr+j);
2629         page_index_t index = find_page_index(ptr);
2630
2631         /* Check that it's in the dynamic space */
2632         if (index != -1)
2633             if (/* Does it point to a younger or the temp. generation? */
2634                 ((page_table[index].allocated != FREE_PAGE_FLAG)
2635                  && (page_table[index].bytes_used != 0)
2636                  && ((page_table[index].gen < gen)
2637                      || (page_table[index].gen == SCRATCH_GENERATION)))
2638
2639                 /* Or does it point within a current gc_alloc() region? */
2640                 || ((boxed_region.start_addr <= ptr)
2641                     && (ptr <= boxed_region.free_pointer))
2642                 || ((unboxed_region.start_addr <= ptr)
2643                     && (ptr <= unboxed_region.free_pointer))) {
2644                 wp_it = 0;
2645                 break;
2646             }
2647     }
2648
2649     if (wp_it == 1) {
2650         /* Write-protect the page. */
2651         /*FSHOW((stderr, "/write-protecting page %d gen %d\n", page, gen));*/
2652
2653         os_protect((void *)page_addr,
2654                    PAGE_BYTES,
2655                    OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
2656
2657         /* Note the page as protected in the page tables. */
2658         page_table[page].write_protected = 1;
2659     }
2660
2661     return (wp_it);
2662 }
2663
2664 /* Scavenge a generation.
2665  *
2666  * This will not resolve all pointers when generation is the new
2667  * space, as new objects may be added which are not checked here - use
2668  * scavenge_newspace generation.
2669  *
2670  * Write-protected pages should not have any pointers to the
2671  * from_space so do need scavenging; thus write-protected pages are
2672  * not always scavenged. There is some code to check that these pages
2673  * are not written; but to check fully the write-protected pages need
2674  * to be scavenged by disabling the code to skip them.
2675  *
2676  * Under the current scheme when a generation is GCed the younger
2677  * generations will be empty. So, when a generation is being GCed it
2678  * is only necessary to scavenge the older generations for pointers
2679  * not the younger. So a page that does not have pointers to younger
2680  * generations does not need to be scavenged.
2681  *
2682  * The write-protection can be used to note pages that don't have
2683  * pointers to younger pages. But pages can be written without having
2684  * pointers to younger generations. After the pages are scavenged here
2685  * they can be scanned for pointers to younger generations and if
2686  * there are none the page can be write-protected.
2687  *
2688  * One complication is when the newspace is the top temp. generation.
2689  *
2690  * Enabling SC_GEN_CK scavenges the write-protected pages and checks
2691  * that none were written, which they shouldn't be as they should have
2692  * no pointers to younger generations. This breaks down for weak
2693  * pointers as the objects contain a link to the next and are written
2694  * if a weak pointer is scavenged. Still it's a useful check. */
2695 static void
2696 scavenge_generation(generation_index_t generation)
2697 {
2698     page_index_t i;
2699     int num_wp = 0;
2700
2701 #define SC_GEN_CK 0
2702 #if SC_GEN_CK
2703     /* Clear the write_protected_cleared flags on all pages. */
2704     for (i = 0; i < NUM_PAGES; i++)
2705         page_table[i].write_protected_cleared = 0;
2706 #endif
2707
2708     for (i = 0; i < last_free_page; i++) {
2709         if ((page_table[i].allocated & BOXED_PAGE_FLAG)
2710             && (page_table[i].bytes_used != 0)
2711             && (page_table[i].gen == generation)) {
2712             page_index_t last_page,j;
2713             int write_protected=1;
2714
2715             /* This should be the start of a region */
2716             gc_assert(page_table[i].first_object_offset == 0);
2717
2718             /* Now work forward until the end of the region */
2719             for (last_page = i; ; last_page++) {
2720                 write_protected =
2721                     write_protected && page_table[last_page].write_protected;
2722                 if ((page_table[last_page].bytes_used < PAGE_BYTES)
2723                     /* Or it is PAGE_BYTES and is the last in the block */
2724                     || (!(page_table[last_page+1].allocated & BOXED_PAGE_FLAG))
2725                     || (page_table[last_page+1].bytes_used == 0)
2726                     || (page_table[last_page+1].gen != generation)
2727                     || (page_table[last_page+1].first_object_offset == 0))
2728                     break;
2729             }
2730             if (!write_protected) {
2731                 scavenge(page_address(i),
2732                          (page_table[last_page].bytes_used +
2733                           (last_page-i)*PAGE_BYTES)/N_WORD_BYTES);
2734
2735                 /* Now scan the pages and write protect those that
2736                  * don't have pointers to younger generations. */
2737                 if (enable_page_protection) {
2738                     for (j = i; j <= last_page; j++) {
2739                         num_wp += update_page_write_prot(j);
2740                     }
2741                 }
2742             }
2743             i = last_page;
2744         }
2745     }
2746     if ((gencgc_verbose > 1) && (num_wp != 0)) {
2747         FSHOW((stderr,
2748                "/write protected %d pages within generation %d\n",
2749                num_wp, generation));
2750     }
2751
2752 #if SC_GEN_CK
2753     /* Check that none of the write_protected pages in this generation
2754      * have been written to. */
2755     for (i = 0; i < NUM_PAGES; i++) {
2756         if ((page_table[i].allocation != FREE_PAGE_FLAG)
2757             && (page_table[i].bytes_used != 0)
2758             && (page_table[i].gen == generation)
2759             && (page_table[i].write_protected_cleared != 0)) {
2760             FSHOW((stderr, "/scavenge_generation() %d\n", generation));
2761             FSHOW((stderr,
2762                    "/page bytes_used=%d first_object_offset=%d dont_move=%d\n",
2763                     page_table[i].bytes_used,
2764                     page_table[i].first_object_offset,
2765                     page_table[i].dont_move));
2766             lose("write to protected page %d in scavenge_generation()", i);
2767         }
2768     }
2769 #endif
2770 }
2771
2772 \f
2773 /* Scavenge a newspace generation. As it is scavenged new objects may
2774  * be allocated to it; these will also need to be scavenged. This
2775  * repeats until there are no more objects unscavenged in the
2776  * newspace generation.
2777  *
2778  * To help improve the efficiency, areas written are recorded by
2779  * gc_alloc() and only these scavenged. Sometimes a little more will be
2780  * scavenged, but this causes no harm. An easy check is done that the
2781  * scavenged bytes equals the number allocated in the previous
2782  * scavenge.
2783  *
2784  * Write-protected pages are not scanned except if they are marked
2785  * dont_move in which case they may have been promoted and still have
2786  * pointers to the from space.
2787  *
2788  * Write-protected pages could potentially be written by alloc however
2789  * to avoid having to handle re-scavenging of write-protected pages
2790  * gc_alloc() does not write to write-protected pages.
2791  *
2792  * New areas of objects allocated are recorded alternatively in the two
2793  * new_areas arrays below. */
2794 static struct new_area new_areas_1[NUM_NEW_AREAS];
2795 static struct new_area new_areas_2[NUM_NEW_AREAS];
2796
2797 /* Do one full scan of the new space generation. This is not enough to
2798  * complete the job as new objects may be added to the generation in
2799  * the process which are not scavenged. */
2800 static void
2801 scavenge_newspace_generation_one_scan(generation_index_t generation)
2802 {
2803     page_index_t i;
2804
2805     FSHOW((stderr,
2806            "/starting one full scan of newspace generation %d\n",
2807            generation));
2808     for (i = 0; i < last_free_page; i++) {
2809         /* Note that this skips over open regions when it encounters them. */
2810         if ((page_table[i].allocated & BOXED_PAGE_FLAG)
2811             && (page_table[i].bytes_used != 0)
2812             && (page_table[i].gen == generation)
2813             && ((page_table[i].write_protected == 0)
2814                 /* (This may be redundant as write_protected is now
2815                  * cleared before promotion.) */
2816                 || (page_table[i].dont_move == 1))) {
2817             page_index_t last_page;
2818             int all_wp=1;
2819
2820             /* The scavenge will start at the first_object_offset of page i.
2821              *
2822              * We need to find the full extent of this contiguous
2823              * block in case objects span pages.
2824              *
2825              * Now work forward until the end of this contiguous area
2826              * is found. A small area is preferred as there is a
2827              * better chance of its pages being write-protected. */
2828             for (last_page = i; ;last_page++) {
2829                 /* If all pages are write-protected and movable,
2830                  * then no need to scavenge */
2831                 all_wp=all_wp && page_table[last_page].write_protected &&
2832                     !page_table[last_page].dont_move;
2833
2834                 /* Check whether this is the last page in this
2835                  * contiguous block */
2836                 if ((page_table[last_page].bytes_used < PAGE_BYTES)
2837                     /* Or it is PAGE_BYTES and is the last in the block */
2838                     || (!(page_table[last_page+1].allocated & BOXED_PAGE_FLAG))
2839                     || (page_table[last_page+1].bytes_used == 0)
2840                     || (page_table[last_page+1].gen != generation)
2841                     || (page_table[last_page+1].first_object_offset == 0))
2842                     break;
2843             }
2844
2845             /* Do a limited check for write-protected pages.  */
2846             if (!all_wp) {
2847                 long size;
2848
2849                 size = (page_table[last_page].bytes_used
2850                         + (last_page-i)*PAGE_BYTES
2851                         - page_table[i].first_object_offset)/N_WORD_BYTES;
2852                 new_areas_ignore_page = last_page;
2853
2854                 scavenge(page_address(i) +
2855                          page_table[i].first_object_offset,
2856                          size);
2857
2858             }
2859             i = last_page;
2860         }
2861     }
2862     FSHOW((stderr,
2863            "/done with one full scan of newspace generation %d\n",
2864            generation));
2865 }
2866
2867 /* Do a complete scavenge of the newspace generation. */
2868 static void
2869 scavenge_newspace_generation(generation_index_t generation)
2870 {
2871     long i;
2872
2873     /* the new_areas array currently being written to by gc_alloc() */
2874     struct new_area (*current_new_areas)[] = &new_areas_1;
2875     long current_new_areas_index;
2876
2877     /* the new_areas created by the previous scavenge cycle */
2878     struct new_area (*previous_new_areas)[] = NULL;
2879     long previous_new_areas_index;
2880
2881     /* Flush the current regions updating the tables. */
2882     gc_alloc_update_all_page_tables();
2883
2884     /* Turn on the recording of new areas by gc_alloc(). */
2885     new_areas = current_new_areas;
2886     new_areas_index = 0;
2887
2888     /* Don't need to record new areas that get scavenged anyway during
2889      * scavenge_newspace_generation_one_scan. */
2890     record_new_objects = 1;
2891
2892     /* Start with a full scavenge. */
2893     scavenge_newspace_generation_one_scan(generation);
2894
2895     /* Record all new areas now. */
2896     record_new_objects = 2;
2897
2898     /* Flush the current regions updating the tables. */
2899     gc_alloc_update_all_page_tables();
2900
2901     /* Grab new_areas_index. */
2902     current_new_areas_index = new_areas_index;
2903
2904     /*FSHOW((stderr,
2905              "The first scan is finished; current_new_areas_index=%d.\n",
2906              current_new_areas_index));*/
2907
2908     while (current_new_areas_index > 0) {
2909         /* Move the current to the previous new areas */
2910         previous_new_areas = current_new_areas;
2911         previous_new_areas_index = current_new_areas_index;
2912
2913         /* Scavenge all the areas in previous new areas. Any new areas
2914          * allocated are saved in current_new_areas. */
2915
2916         /* Allocate an array for current_new_areas; alternating between
2917          * new_areas_1 and 2 */
2918         if (previous_new_areas == &new_areas_1)
2919             current_new_areas = &new_areas_2;
2920         else
2921             current_new_areas = &new_areas_1;
2922
2923         /* Set up for gc_alloc(). */
2924         new_areas = current_new_areas;
2925         new_areas_index = 0;
2926
2927         /* Check whether previous_new_areas had overflowed. */
2928         if (previous_new_areas_index >= NUM_NEW_AREAS) {
2929
2930             /* New areas of objects allocated have been lost so need to do a
2931              * full scan to be sure! If this becomes a problem try
2932              * increasing NUM_NEW_AREAS. */
2933             if (gencgc_verbose)
2934                 SHOW("new_areas overflow, doing full scavenge");
2935
2936             /* Don't need to record new areas that get scavenge anyway
2937              * during scavenge_newspace_generation_one_scan. */
2938             record_new_objects = 1;
2939
2940             scavenge_newspace_generation_one_scan(generation);
2941
2942             /* Record all new areas now. */
2943             record_new_objects = 2;
2944
2945             /* Flush the current regions updating the tables. */
2946             gc_alloc_update_all_page_tables();
2947
2948         } else {
2949
2950             /* Work through previous_new_areas. */
2951             for (i = 0; i < previous_new_areas_index; i++) {
2952                 long page = (*previous_new_areas)[i].page;
2953                 long offset = (*previous_new_areas)[i].offset;
2954                 long size = (*previous_new_areas)[i].size / N_WORD_BYTES;
2955                 gc_assert((*previous_new_areas)[i].size % N_WORD_BYTES == 0);
2956                 scavenge(page_address(page)+offset, size);
2957             }
2958
2959             /* Flush the current regions updating the tables. */
2960             gc_alloc_update_all_page_tables();
2961         }
2962
2963         current_new_areas_index = new_areas_index;
2964
2965         /*FSHOW((stderr,
2966                  "The re-scan has finished; current_new_areas_index=%d.\n",
2967                  current_new_areas_index));*/
2968     }
2969
2970     /* Turn off recording of areas allocated by gc_alloc(). */
2971     record_new_objects = 0;
2972
2973 #if SC_NS_GEN_CK
2974     /* Check that none of the write_protected pages in this generation
2975      * have been written to. */
2976     for (i = 0; i < NUM_PAGES; i++) {
2977         if ((page_table[i].allocation != FREE_PAGE_FLAG)
2978             && (page_table[i].bytes_used != 0)
2979             && (page_table[i].gen == generation)
2980             && (page_table[i].write_protected_cleared != 0)
2981             && (page_table[i].dont_move == 0)) {
2982             lose("write protected page %d written to in scavenge_newspace_generation\ngeneration=%d dont_move=%d",
2983                  i, generation, page_table[i].dont_move);
2984         }
2985     }
2986 #endif
2987 }
2988 \f
2989 /* Un-write-protect all the pages in from_space. This is done at the
2990  * start of a GC else there may be many page faults while scavenging
2991  * the newspace (I've seen drive the system time to 99%). These pages
2992  * would need to be unprotected anyway before unmapping in
2993  * free_oldspace; not sure what effect this has on paging.. */
2994 static void
2995 unprotect_oldspace(void)
2996 {
2997     page_index_t i;
2998
2999     for (i = 0; i < last_free_page; i++) {
3000         if ((page_table[i].allocated != FREE_PAGE_FLAG)
3001             && (page_table[i].bytes_used != 0)
3002             && (page_table[i].gen == from_space)) {
3003             void *page_start;
3004
3005             page_start = (void *)page_address(i);
3006
3007             /* Remove any write-protection. We should be able to rely
3008              * on the write-protect flag to avoid redundant calls. */
3009             if (page_table[i].write_protected) {
3010                 os_protect(page_start, PAGE_BYTES, OS_VM_PROT_ALL);
3011                 page_table[i].write_protected = 0;
3012             }
3013         }
3014     }
3015 }
3016
3017 /* Work through all the pages and free any in from_space. This
3018  * assumes that all objects have been copied or promoted to an older
3019  * generation. Bytes_allocated and the generation bytes_allocated
3020  * counter are updated. The number of bytes freed is returned. */
3021 static long
3022 free_oldspace(void)
3023 {
3024     long bytes_freed = 0;
3025     page_index_t first_page, last_page;
3026
3027     first_page = 0;
3028
3029     do {
3030         /* Find a first page for the next region of pages. */
3031         while ((first_page < last_free_page)
3032                && ((page_table[first_page].allocated == FREE_PAGE_FLAG)
3033                    || (page_table[first_page].bytes_used == 0)
3034                    || (page_table[first_page].gen != from_space)))
3035             first_page++;
3036
3037         if (first_page >= last_free_page)
3038             break;
3039
3040         /* Find the last page of this region. */
3041         last_page = first_page;
3042
3043         do {
3044             /* Free the page. */
3045             bytes_freed += page_table[last_page].bytes_used;
3046             generations[page_table[last_page].gen].bytes_allocated -=
3047                 page_table[last_page].bytes_used;
3048             page_table[last_page].allocated = FREE_PAGE_FLAG;
3049             page_table[last_page].bytes_used = 0;
3050
3051             /* Remove any write-protection. We should be able to rely
3052              * on the write-protect flag to avoid redundant calls. */
3053             {
3054                 void  *page_start = (void *)page_address(last_page);
3055
3056                 if (page_table[last_page].write_protected) {
3057                     os_protect(page_start, PAGE_BYTES, OS_VM_PROT_ALL);
3058                     page_table[last_page].write_protected = 0;
3059                 }
3060             }
3061             last_page++;
3062         }
3063         while ((last_page < last_free_page)
3064                && (page_table[last_page].allocated != FREE_PAGE_FLAG)
3065                && (page_table[last_page].bytes_used != 0)
3066                && (page_table[last_page].gen == from_space));
3067
3068         /* Zero pages from first_page to (last_page-1).
3069          *
3070          * FIXME: Why not use os_zero(..) function instead of
3071          * hand-coding this again? (Check other gencgc_unmap_zero
3072          * stuff too. */
3073         if (gencgc_unmap_zero) {
3074             void *page_start, *addr;
3075
3076             page_start = (void *)page_address(first_page);
3077
3078             os_invalidate(page_start, PAGE_BYTES*(last_page-first_page));
3079             addr = os_validate(page_start, PAGE_BYTES*(last_page-first_page));
3080             if (addr == NULL || addr != page_start) {
3081                 lose("free_oldspace: page moved, 0x%08x ==> 0x%08x",page_start,
3082                      addr);
3083             }
3084         } else {
3085             long *page_start;
3086
3087             page_start = (long *)page_address(first_page);
3088             memset(page_start, 0,PAGE_BYTES*(last_page-first_page));
3089         }
3090
3091         first_page = last_page;
3092
3093     } while (first_page < last_free_page);
3094
3095     bytes_allocated -= bytes_freed;
3096     return bytes_freed;
3097 }
3098 \f
3099 #if 0
3100 /* Print some information about a pointer at the given address. */
3101 static void
3102 print_ptr(lispobj *addr)
3103 {
3104     /* If addr is in the dynamic space then out the page information. */
3105     page_index_t pi1 = find_page_index((void*)addr);
3106
3107     if (pi1 != -1)
3108         fprintf(stderr,"  %x: page %d  alloc %d  gen %d  bytes_used %d  offset %d  dont_move %d\n",
3109                 (unsigned long) addr,
3110                 pi1,
3111                 page_table[pi1].allocated,
3112                 page_table[pi1].gen,
3113                 page_table[pi1].bytes_used,
3114                 page_table[pi1].first_object_offset,
3115                 page_table[pi1].dont_move);
3116     fprintf(stderr,"  %x %x %x %x (%x) %x %x %x %x\n",
3117             *(addr-4),
3118             *(addr-3),
3119             *(addr-2),
3120             *(addr-1),
3121             *(addr-0),
3122             *(addr+1),
3123             *(addr+2),
3124             *(addr+3),
3125             *(addr+4));
3126 }
3127 #endif
3128
3129 extern long undefined_tramp;
3130
3131 static void
3132 verify_space(lispobj *start, size_t words)
3133 {
3134     int is_in_dynamic_space = (find_page_index((void*)start) != -1);
3135     int is_in_readonly_space =
3136         (READ_ONLY_SPACE_START <= (unsigned long)start &&
3137          (unsigned long)start < SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0));
3138
3139     while (words > 0) {
3140         size_t count = 1;
3141         lispobj thing = *(lispobj*)start;
3142
3143         if (is_lisp_pointer(thing)) {
3144             page_index_t page_index = find_page_index((void*)thing);
3145             long to_readonly_space =
3146                 (READ_ONLY_SPACE_START <= thing &&
3147                  thing < SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0));
3148             long to_static_space =
3149                 (STATIC_SPACE_START <= thing &&
3150                  thing < SymbolValue(STATIC_SPACE_FREE_POINTER,0));
3151
3152             /* Does it point to the dynamic space? */
3153             if (page_index != -1) {
3154                 /* If it's within the dynamic space it should point to a used
3155                  * page. XX Could check the offset too. */
3156                 if ((page_table[page_index].allocated != FREE_PAGE_FLAG)
3157                     && (page_table[page_index].bytes_used == 0))
3158                     lose ("Ptr %x @ %x sees free page.", thing, start);
3159                 /* Check that it doesn't point to a forwarding pointer! */
3160                 if (*((lispobj *)native_pointer(thing)) == 0x01) {
3161                     lose("Ptr %x @ %x sees forwarding ptr.", thing, start);
3162                 }
3163                 /* Check that its not in the RO space as it would then be a
3164                  * pointer from the RO to the dynamic space. */
3165                 if (is_in_readonly_space) {
3166                     lose("ptr to dynamic space %x from RO space %x",
3167                          thing, start);
3168                 }
3169                 /* Does it point to a plausible object? This check slows
3170                  * it down a lot (so it's commented out).
3171                  *
3172                  * "a lot" is serious: it ate 50 minutes cpu time on
3173                  * my duron 950 before I came back from lunch and
3174                  * killed it.
3175                  *
3176                  *   FIXME: Add a variable to enable this
3177                  * dynamically. */
3178                 /*
3179                 if (!possibly_valid_dynamic_space_pointer((lispobj *)thing)) {
3180                     lose("ptr %x to invalid object %x", thing, start);
3181                 }
3182                 */
3183             } else {
3184                 /* Verify that it points to another valid space. */
3185                 if (!to_readonly_space && !to_static_space
3186                     && (thing != (unsigned long)&undefined_tramp)) {
3187                     lose("Ptr %x @ %x sees junk.", thing, start);
3188                 }
3189             }
3190         } else {
3191             if (!(fixnump(thing))) {
3192                 /* skip fixnums */
3193                 switch(widetag_of(*start)) {
3194
3195                     /* boxed objects */
3196                 case SIMPLE_VECTOR_WIDETAG:
3197                 case RATIO_WIDETAG:
3198                 case COMPLEX_WIDETAG:
3199                 case SIMPLE_ARRAY_WIDETAG:
3200                 case COMPLEX_BASE_STRING_WIDETAG:
3201 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
3202                 case COMPLEX_CHARACTER_STRING_WIDETAG:
3203 #endif
3204                 case COMPLEX_VECTOR_NIL_WIDETAG:
3205                 case COMPLEX_BIT_VECTOR_WIDETAG:
3206                 case COMPLEX_VECTOR_WIDETAG:
3207                 case COMPLEX_ARRAY_WIDETAG:
3208                 case CLOSURE_HEADER_WIDETAG:
3209                 case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
3210                 case VALUE_CELL_HEADER_WIDETAG:
3211                 case SYMBOL_HEADER_WIDETAG:
3212                 case CHARACTER_WIDETAG:
3213 #if N_WORD_BITS == 64
3214                 case SINGLE_FLOAT_WIDETAG:
3215 #endif
3216                 case UNBOUND_MARKER_WIDETAG:
3217                 case INSTANCE_HEADER_WIDETAG:
3218                 case FDEFN_WIDETAG:
3219                     count = 1;
3220                     break;
3221
3222                 case CODE_HEADER_WIDETAG:
3223                     {
3224                         lispobj object = *start;
3225                         struct code *code;
3226                         long nheader_words, ncode_words, nwords;
3227                         lispobj fheaderl;
3228                         struct simple_fun *fheaderp;
3229
3230                         code = (struct code *) start;
3231
3232                         /* Check that it's not in the dynamic space.
3233                          * FIXME: Isn't is supposed to be OK for code
3234                          * objects to be in the dynamic space these days? */
3235                         if (is_in_dynamic_space
3236                             /* It's ok if it's byte compiled code. The trace
3237                              * table offset will be a fixnum if it's x86
3238                              * compiled code - check.
3239                              *
3240                              * FIXME: #^#@@! lack of abstraction here..
3241                              * This line can probably go away now that
3242                              * there's no byte compiler, but I've got
3243                              * too much to worry about right now to try
3244                              * to make sure. -- WHN 2001-10-06 */
3245                             && fixnump(code->trace_table_offset)
3246                             /* Only when enabled */
3247                             && verify_dynamic_code_check) {
3248                             FSHOW((stderr,
3249                                    "/code object at %x in the dynamic space\n",
3250                                    start));
3251                         }
3252
3253                         ncode_words = fixnum_value(code->code_size);
3254                         nheader_words = HeaderValue(object);
3255                         nwords = ncode_words + nheader_words;
3256                         nwords = CEILING(nwords, 2);
3257                         /* Scavenge the boxed section of the code data block */
3258                         verify_space(start + 1, nheader_words - 1);
3259
3260                         /* Scavenge the boxed section of each function
3261                          * object in the code data block. */
3262                         fheaderl = code->entry_points;
3263                         while (fheaderl != NIL) {
3264                             fheaderp =
3265                                 (struct simple_fun *) native_pointer(fheaderl);
3266                             gc_assert(widetag_of(fheaderp->header) == SIMPLE_FUN_HEADER_WIDETAG);
3267                             verify_space(&fheaderp->name, 1);
3268                             verify_space(&fheaderp->arglist, 1);
3269                             verify_space(&fheaderp->type, 1);
3270                             fheaderl = fheaderp->next;
3271                         }
3272                         count = nwords;
3273                         break;
3274                     }
3275
3276                     /* unboxed objects */
3277                 case BIGNUM_WIDETAG:
3278 #if N_WORD_BITS != 64
3279                 case SINGLE_FLOAT_WIDETAG:
3280 #endif
3281                 case DOUBLE_FLOAT_WIDETAG:
3282 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
3283                 case LONG_FLOAT_WIDETAG:
3284 #endif
3285 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
3286                 case COMPLEX_SINGLE_FLOAT_WIDETAG:
3287 #endif
3288 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
3289                 case COMPLEX_DOUBLE_FLOAT_WIDETAG:
3290 #endif
3291 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
3292                 case COMPLEX_LONG_FLOAT_WIDETAG:
3293 #endif
3294                 case SIMPLE_BASE_STRING_WIDETAG:
3295 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
3296                 case SIMPLE_CHARACTER_STRING_WIDETAG:
3297 #endif
3298                 case SIMPLE_BIT_VECTOR_WIDETAG:
3299                 case SIMPLE_ARRAY_NIL_WIDETAG:
3300                 case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
3301                 case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
3302                 case SIMPLE_ARRAY_UNSIGNED_BYTE_7_WIDETAG:
3303                 case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
3304                 case SIMPLE_ARRAY_UNSIGNED_BYTE_15_WIDETAG:
3305                 case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
3306 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG
3307                 case SIMPLE_ARRAY_UNSIGNED_BYTE_29_WIDETAG:
3308 #endif
3309                 case SIMPLE_ARRAY_UNSIGNED_BYTE_31_WIDETAG:
3310                 case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
3311 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG
3312                 case SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG:
3313 #endif
3314 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG
3315                 case SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG:
3316 #endif
3317 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG
3318                 case SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG:
3319 #endif
3320 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
3321                 case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
3322 #endif
3323 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
3324                 case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
3325 #endif
3326 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
3327                 case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
3328 #endif
3329 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
3330                 case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
3331 #endif
3332 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_61_WIDETAG
3333                 case SIMPLE_ARRAY_SIGNED_BYTE_61_WIDETAG:
3334 #endif
3335 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG
3336                 case SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG:
3337 #endif
3338                 case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
3339                 case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
3340 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
3341                 case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
3342 #endif
3343 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
3344                 case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
3345 #endif
3346 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
3347                 case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
3348 #endif
3349 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
3350                 case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
3351 #endif
3352                 case SAP_WIDETAG:
3353                 case WEAK_POINTER_WIDETAG:
3354                     count = (sizetab[widetag_of(*start)])(start);
3355                     break;
3356
3357                 default:
3358                     gc_abort();
3359                 }
3360             }
3361         }
3362         start += count;
3363         words -= count;
3364     }
3365 }
3366
3367 static void
3368 verify_gc(void)
3369 {
3370     /* FIXME: It would be nice to make names consistent so that
3371      * foo_size meant size *in* *bytes* instead of size in some
3372      * arbitrary units. (Yes, this caused a bug, how did you guess?:-)
3373      * Some counts of lispobjs are called foo_count; it might be good
3374      * to grep for all foo_size and rename the appropriate ones to
3375      * foo_count. */
3376     long read_only_space_size =
3377         (lispobj*)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0)
3378         - (lispobj*)READ_ONLY_SPACE_START;
3379     long static_space_size =
3380         (lispobj*)SymbolValue(STATIC_SPACE_FREE_POINTER,0)
3381         - (lispobj*)STATIC_SPACE_START;
3382     struct thread *th;
3383     for_each_thread(th) {
3384     long binding_stack_size =
3385             (lispobj*)SymbolValue(BINDING_STACK_POINTER,th)
3386             - (lispobj*)th->binding_stack_start;
3387         verify_space(th->binding_stack_start, binding_stack_size);
3388     }
3389     verify_space((lispobj*)READ_ONLY_SPACE_START, read_only_space_size);
3390     verify_space((lispobj*)STATIC_SPACE_START   , static_space_size);
3391 }
3392
3393 static void
3394 verify_generation(generation_index_t generation)
3395 {
3396     page_index_t i;
3397
3398     for (i = 0; i < last_free_page; i++) {
3399         if ((page_table[i].allocated != FREE_PAGE_FLAG)
3400             && (page_table[i].bytes_used != 0)
3401             && (page_table[i].gen == generation)) {
3402             page_index_t last_page;
3403             int region_allocation = page_table[i].allocated;
3404
3405             /* This should be the start of a contiguous block */
3406             gc_assert(page_table[i].first_object_offset == 0);
3407
3408             /* Need to find the full extent of this contiguous block in case
3409                objects span pages. */
3410
3411             /* Now work forward until the end of this contiguous area is
3412                found. */
3413             for (last_page = i; ;last_page++)
3414                 /* Check whether this is the last page in this contiguous
3415                  * block. */
3416                 if ((page_table[last_page].bytes_used < PAGE_BYTES)
3417                     /* Or it is PAGE_BYTES and is the last in the block */
3418                     || (page_table[last_page+1].allocated != region_allocation)
3419                     || (page_table[last_page+1].bytes_used == 0)
3420                     || (page_table[last_page+1].gen != generation)
3421                     || (page_table[last_page+1].first_object_offset == 0))
3422                     break;
3423
3424             verify_space(page_address(i), (page_table[last_page].bytes_used
3425                                            + (last_page-i)*PAGE_BYTES)/N_WORD_BYTES);
3426             i = last_page;
3427         }
3428     }
3429 }
3430
3431 /* Check that all the free space is zero filled. */
3432 static void
3433 verify_zero_fill(void)
3434 {
3435     page_index_t page;
3436
3437     for (page = 0; page < last_free_page; page++) {
3438         if (page_table[page].allocated == FREE_PAGE_FLAG) {
3439             /* The whole page should be zero filled. */
3440             long *start_addr = (long *)page_address(page);
3441             long size = 1024;
3442             long i;
3443             for (i = 0; i < size; i++) {
3444                 if (start_addr[i] != 0) {
3445                     lose("free page not zero at %x", start_addr + i);
3446                 }
3447             }
3448         } else {
3449             long free_bytes = PAGE_BYTES - page_table[page].bytes_used;
3450             if (free_bytes > 0) {
3451                 long *start_addr = (long *)((unsigned long)page_address(page)
3452                                           + page_table[page].bytes_used);
3453                 long size = free_bytes / N_WORD_BYTES;
3454                 long i;
3455                 for (i = 0; i < size; i++) {
3456                     if (start_addr[i] != 0) {
3457                         lose("free region not zero at %x", start_addr + i);
3458                     }
3459                 }
3460             }
3461         }
3462     }
3463 }
3464
3465 /* External entry point for verify_zero_fill */
3466 void
3467 gencgc_verify_zero_fill(void)
3468 {
3469     /* Flush the alloc regions updating the tables. */
3470     gc_alloc_update_all_page_tables();
3471     SHOW("verifying zero fill");
3472     verify_zero_fill();
3473 }
3474
3475 static void
3476 verify_dynamic_space(void)
3477 {
3478     generation_index_t i;
3479
3480     for (i = 0; i <= HIGHEST_NORMAL_GENERATION; i++)
3481         verify_generation(i);
3482
3483     if (gencgc_enable_verify_zero_fill)
3484         verify_zero_fill();
3485 }
3486 \f
3487 /* Write-protect all the dynamic boxed pages in the given generation. */
3488 static void
3489 write_protect_generation_pages(generation_index_t generation)
3490 {
3491     page_index_t i;
3492
3493     gc_assert(generation < SCRATCH_GENERATION);
3494
3495     for (i = 0; i < last_free_page; i++)
3496         if ((page_table[i].allocated == BOXED_PAGE_FLAG)
3497             && (page_table[i].bytes_used != 0)
3498             && !page_table[i].dont_move
3499             && (page_table[i].gen == generation))  {
3500             void *page_start;
3501
3502             page_start = (void *)page_address(i);
3503
3504             os_protect(page_start,
3505                        PAGE_BYTES,
3506                        OS_VM_PROT_READ | OS_VM_PROT_EXECUTE);
3507
3508             /* Note the page as protected in the page tables. */
3509             page_table[i].write_protected = 1;
3510         }
3511
3512     if (gencgc_verbose > 1) {
3513         FSHOW((stderr,
3514                "/write protected %d of %d pages in generation %d\n",
3515                count_write_protect_generation_pages(generation),
3516                count_generation_pages(generation),
3517                generation));
3518     }
3519 }
3520
3521 /* Garbage collect a generation. If raise is 0 then the remains of the
3522  * generation are not raised to the next generation. */
3523 static void
3524 garbage_collect_generation(generation_index_t generation, int raise)
3525 {
3526     unsigned long bytes_freed;
3527     page_index_t i;
3528     unsigned long static_space_size;
3529     struct thread *th;
3530     gc_assert(generation <= HIGHEST_NORMAL_GENERATION);
3531
3532     /* The oldest generation can't be raised. */
3533     gc_assert((generation != HIGHEST_NORMAL_GENERATION) || (raise == 0));
3534
3535     /* Initialize the weak pointer list. */
3536     weak_pointers = NULL;
3537
3538     /* When a generation is not being raised it is transported to a
3539      * temporary generation (NUM_GENERATIONS), and lowered when
3540      * done. Set up this new generation. There should be no pages
3541      * allocated to it yet. */
3542     if (!raise) {
3543          gc_assert(generations[SCRATCH_GENERATION].bytes_allocated == 0);
3544     }
3545
3546     /* Set the global src and dest. generations */
3547     from_space = generation;
3548     if (raise)
3549         new_space = generation+1;
3550     else
3551         new_space = SCRATCH_GENERATION;
3552
3553     /* Change to a new space for allocation, resetting the alloc_start_page */
3554     gc_alloc_generation = new_space;
3555     generations[new_space].alloc_start_page = 0;
3556     generations[new_space].alloc_unboxed_start_page = 0;
3557     generations[new_space].alloc_large_start_page = 0;
3558     generations[new_space].alloc_large_unboxed_start_page = 0;
3559
3560     /* Before any pointers are preserved, the dont_move flags on the
3561      * pages need to be cleared. */
3562     for (i = 0; i < last_free_page; i++)
3563         if(page_table[i].gen==from_space)
3564             page_table[i].dont_move = 0;
3565
3566     /* Un-write-protect the old-space pages. This is essential for the
3567      * promoted pages as they may contain pointers into the old-space
3568      * which need to be scavenged. It also helps avoid unnecessary page
3569      * faults as forwarding pointers are written into them. They need to
3570      * be un-protected anyway before unmapping later. */
3571     unprotect_oldspace();
3572
3573     /* Scavenge the stacks' conservative roots. */
3574
3575     /* there are potentially two stacks for each thread: the main
3576      * stack, which may contain Lisp pointers, and the alternate stack.
3577      * We don't ever run Lisp code on the altstack, but it may
3578      * host a sigcontext with lisp objects in it */
3579
3580     /* what we need to do: (1) find the stack pointer for the main
3581      * stack; scavenge it (2) find the interrupt context on the
3582      * alternate stack that might contain lisp values, and scavenge
3583      * that */
3584
3585     /* we assume that none of the preceding applies to the thread that
3586      * initiates GC.  If you ever call GC from inside an altstack
3587      * handler, you will lose. */
3588     for_each_thread(th) {
3589         void **ptr;
3590         void **esp=(void **)-1;
3591 #ifdef LISP_FEATURE_SB_THREAD
3592         long i,free;
3593         if(th==arch_os_get_current_thread()) {
3594             /* Somebody is going to burn in hell for this, but casting
3595              * it in two steps shuts gcc up about strict aliasing. */
3596             esp = (void **)((void *)&raise);
3597         } else {
3598             void **esp1;
3599             free=fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,th));
3600             for(i=free-1;i>=0;i--) {
3601                 os_context_t *c=th->interrupt_contexts[i];
3602                 esp1 = (void **) *os_context_register_addr(c,reg_SP);
3603                 if (esp1>=(void **)th->control_stack_start &&
3604                     esp1<(void **)th->control_stack_end) {
3605                     if(esp1<esp) esp=esp1;
3606                     for(ptr = (void **)(c+1); ptr>=(void **)c; ptr--) {
3607                         preserve_pointer(*ptr);
3608                     }
3609                 }
3610             }
3611         }
3612 #else
3613         esp = (void **)((void *)&raise);
3614 #endif
3615         for (ptr = (void **)th->control_stack_end; ptr > esp;  ptr--) {
3616             preserve_pointer(*ptr);
3617         }
3618     }
3619
3620 #ifdef QSHOW
3621     if (gencgc_verbose > 1) {
3622         long num_dont_move_pages = count_dont_move_pages();
3623         fprintf(stderr,
3624                 "/non-movable pages due to conservative pointers = %d (%d bytes)\n",
3625                 num_dont_move_pages,
3626                 num_dont_move_pages * PAGE_BYTES);
3627     }
3628 #endif
3629
3630     /* Scavenge all the rest of the roots. */
3631
3632     /* Scavenge the Lisp functions of the interrupt handlers, taking
3633      * care to avoid SIG_DFL and SIG_IGN. */
3634     for (i = 0; i < NSIG; i++) {
3635         union interrupt_handler handler = interrupt_handlers[i];
3636         if (!ARE_SAME_HANDLER(handler.c, SIG_IGN) &&
3637             !ARE_SAME_HANDLER(handler.c, SIG_DFL)) {
3638             scavenge((lispobj *)(interrupt_handlers + i), 1);
3639         }
3640     }
3641     /* Scavenge the binding stacks. */
3642     {
3643         struct thread *th;
3644         for_each_thread(th) {
3645             long len= (lispobj *)SymbolValue(BINDING_STACK_POINTER,th) -
3646                 th->binding_stack_start;
3647             scavenge((lispobj *) th->binding_stack_start,len);
3648 #ifdef LISP_FEATURE_SB_THREAD
3649             /* do the tls as well */
3650             len=fixnum_value(SymbolValue(FREE_TLS_INDEX,0)) -
3651                 (sizeof (struct thread))/(sizeof (lispobj));
3652             scavenge((lispobj *) (th+1),len);
3653 #endif
3654         }
3655     }
3656
3657     /* The original CMU CL code had scavenge-read-only-space code
3658      * controlled by the Lisp-level variable
3659      * *SCAVENGE-READ-ONLY-SPACE*. It was disabled by default, and it
3660      * wasn't documented under what circumstances it was useful or
3661      * safe to turn it on, so it's been turned off in SBCL. If you
3662      * want/need this functionality, and can test and document it,
3663      * please submit a patch. */
3664 #if 0
3665     if (SymbolValue(SCAVENGE_READ_ONLY_SPACE) != NIL) {
3666         unsigned long read_only_space_size =
3667             (lispobj*)SymbolValue(READ_ONLY_SPACE_FREE_POINTER) -
3668             (lispobj*)READ_ONLY_SPACE_START;
3669         FSHOW((stderr,
3670                "/scavenge read only space: %d bytes\n",
3671                read_only_space_size * sizeof(lispobj)));
3672         scavenge( (lispobj *) READ_ONLY_SPACE_START, read_only_space_size);
3673     }
3674 #endif
3675
3676     /* Scavenge static space. */
3677     static_space_size =
3678         (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0) -
3679         (lispobj *)STATIC_SPACE_START;
3680     if (gencgc_verbose > 1) {
3681         FSHOW((stderr,
3682                "/scavenge static space: %d bytes\n",
3683                static_space_size * sizeof(lispobj)));
3684     }
3685     scavenge( (lispobj *) STATIC_SPACE_START, static_space_size);
3686
3687     /* All generations but the generation being GCed need to be
3688      * scavenged. The new_space generation needs special handling as
3689      * objects may be moved in - it is handled separately below. */
3690     for (i = 0; i <= PSEUDO_STATIC_GENERATION; i++) {
3691         if ((i != generation) && (i != new_space)) {
3692             scavenge_generation(i);
3693         }
3694     }
3695
3696     /* Finally scavenge the new_space generation. Keep going until no
3697      * more objects are moved into the new generation */
3698     scavenge_newspace_generation(new_space);
3699
3700     /* FIXME: I tried reenabling this check when debugging unrelated
3701      * GC weirdness ca. sbcl-0.6.12.45, and it failed immediately.
3702      * Since the current GC code seems to work well, I'm guessing that
3703      * this debugging code is just stale, but I haven't tried to
3704      * figure it out. It should be figured out and then either made to
3705      * work or just deleted. */
3706 #define RESCAN_CHECK 0
3707 #if RESCAN_CHECK
3708     /* As a check re-scavenge the newspace once; no new objects should
3709      * be found. */
3710     {
3711         long old_bytes_allocated = bytes_allocated;
3712         long bytes_allocated;
3713
3714         /* Start with a full scavenge. */
3715         scavenge_newspace_generation_one_scan(new_space);
3716
3717         /* Flush the current regions, updating the tables. */
3718         gc_alloc_update_all_page_tables();
3719
3720         bytes_allocated = bytes_allocated - old_bytes_allocated;
3721
3722         if (bytes_allocated != 0) {
3723             lose("Rescan of new_space allocated %d more bytes.",
3724                  bytes_allocated);
3725         }
3726     }
3727 #endif
3728
3729     scan_weak_pointers();
3730
3731     /* Flush the current regions, updating the tables. */
3732     gc_alloc_update_all_page_tables();
3733
3734     /* Free the pages in oldspace, but not those marked dont_move. */
3735     bytes_freed = free_oldspace();
3736
3737     /* If the GC is not raising the age then lower the generation back
3738      * to its normal generation number */
3739     if (!raise) {
3740         for (i = 0; i < last_free_page; i++)
3741             if ((page_table[i].bytes_used != 0)
3742                 && (page_table[i].gen == SCRATCH_GENERATION))
3743                 page_table[i].gen = generation;
3744         gc_assert(generations[generation].bytes_allocated == 0);
3745         generations[generation].bytes_allocated =
3746             generations[SCRATCH_GENERATION].bytes_allocated;
3747         generations[SCRATCH_GENERATION].bytes_allocated = 0;
3748     }
3749
3750     /* Reset the alloc_start_page for generation. */
3751     generations[generation].alloc_start_page = 0;
3752     generations[generation].alloc_unboxed_start_page = 0;
3753     generations[generation].alloc_large_start_page = 0;
3754     generations[generation].alloc_large_unboxed_start_page = 0;
3755
3756     if (generation >= verify_gens) {
3757         if (gencgc_verbose)
3758             SHOW("verifying");
3759         verify_gc();
3760         verify_dynamic_space();
3761     }
3762
3763     /* Set the new gc trigger for the GCed generation. */
3764     generations[generation].gc_trigger =
3765         generations[generation].bytes_allocated
3766         + generations[generation].bytes_consed_between_gc;
3767
3768     if (raise)
3769         generations[generation].num_gc = 0;
3770     else
3771         ++generations[generation].num_gc;
3772 }
3773
3774 /* Update last_free_page, then SymbolValue(ALLOCATION_POINTER). */
3775 long
3776 update_dynamic_space_free_pointer(void)
3777 {
3778     page_index_t last_page = -1, i;
3779
3780     for (i = 0; i < last_free_page; i++)
3781         if ((page_table[i].allocated != FREE_PAGE_FLAG)
3782             && (page_table[i].bytes_used != 0))
3783             last_page = i;
3784
3785     last_free_page = last_page+1;
3786
3787     SetSymbolValue(ALLOCATION_POINTER,
3788                    (lispobj)(((char *)heap_base) + last_free_page*PAGE_BYTES),0);
3789     return 0; /* dummy value: return something ... */
3790 }
3791
3792 /* GC all generations newer than last_gen, raising the objects in each
3793  * to the next older generation - we finish when all generations below
3794  * last_gen are empty.  Then if last_gen is due for a GC, or if
3795  * last_gen==NUM_GENERATIONS (the scratch generation?  eh?) we GC that
3796  * too.  The valid range for last_gen is: 0,1,...,NUM_GENERATIONS.
3797  *
3798  * We stop collecting at gencgc_oldest_gen_to_gc, even if this is less than
3799  * last_gen (oh, and note that by default it is NUM_GENERATIONS-1) */
3800
3801 void
3802 collect_garbage(generation_index_t last_gen)
3803 {
3804     generation_index_t gen = 0, i;
3805     int raise;
3806     int gen_to_wp;
3807
3808     FSHOW((stderr, "/entering collect_garbage(%d)\n", last_gen));
3809
3810     if (last_gen > HIGHEST_NORMAL_GENERATION+1) {
3811         FSHOW((stderr,
3812                "/collect_garbage: last_gen = %d, doing a level 0 GC\n",
3813                last_gen));
3814         last_gen = 0;
3815     }
3816
3817     /* Flush the alloc regions updating the tables. */
3818     gc_alloc_update_all_page_tables();
3819
3820     /* Verify the new objects created by Lisp code. */
3821     if (pre_verify_gen_0) {
3822         FSHOW((stderr, "pre-checking generation 0\n"));
3823         verify_generation(0);
3824     }
3825
3826     if (gencgc_verbose > 1)
3827         print_generation_stats(0);
3828
3829     do {
3830         /* Collect the generation. */
3831
3832         if (gen >= gencgc_oldest_gen_to_gc) {
3833             /* Never raise the oldest generation. */
3834             raise = 0;
3835         } else {
3836             raise =
3837                 (gen < last_gen)
3838                 || (generations[gen].num_gc >= generations[gen].trigger_age);
3839         }
3840
3841         if (gencgc_verbose > 1) {
3842             FSHOW((stderr,
3843                    "starting GC of generation %d with raise=%d alloc=%d trig=%d GCs=%d\n",
3844                    gen,
3845                    raise,
3846                    generations[gen].bytes_allocated,
3847                    generations[gen].gc_trigger,
3848                    generations[gen].num_gc));
3849         }
3850
3851         /* If an older generation is being filled, then update its
3852          * memory age. */
3853         if (raise == 1) {
3854             generations[gen+1].cum_sum_bytes_allocated +=
3855                 generations[gen+1].bytes_allocated;
3856         }
3857
3858         garbage_collect_generation(gen, raise);
3859
3860         /* Reset the memory age cum_sum. */
3861         generations[gen].cum_sum_bytes_allocated = 0;
3862
3863         if (gencgc_verbose > 1) {
3864             FSHOW((stderr, "GC of generation %d finished:\n", gen));
3865             print_generation_stats(0);
3866         }
3867
3868         gen++;
3869     } while ((gen <= gencgc_oldest_gen_to_gc)
3870              && ((gen < last_gen)
3871                  || ((gen <= gencgc_oldest_gen_to_gc)
3872                      && raise
3873                      && (generations[gen].bytes_allocated
3874                          > generations[gen].gc_trigger)
3875                      && (gen_av_mem_age(gen)
3876                          > generations[gen].min_av_mem_age))));
3877
3878     /* Now if gen-1 was raised all generations before gen are empty.
3879      * If it wasn't raised then all generations before gen-1 are empty.
3880      *
3881      * Now objects within this gen's pages cannot point to younger
3882      * generations unless they are written to. This can be exploited
3883      * by write-protecting the pages of gen; then when younger
3884      * generations are GCed only the pages which have been written
3885      * need scanning. */
3886     if (raise)
3887         gen_to_wp = gen;
3888     else
3889         gen_to_wp = gen - 1;
3890
3891     /* There's not much point in WPing pages in generation 0 as it is
3892      * never scavenged (except promoted pages). */
3893     if ((gen_to_wp > 0) && enable_page_protection) {
3894         /* Check that they are all empty. */
3895         for (i = 0; i < gen_to_wp; i++) {
3896             if (generations[i].bytes_allocated)
3897                 lose("trying to write-protect gen. %d when gen. %d nonempty",
3898                      gen_to_wp, i);
3899         }
3900         write_protect_generation_pages(gen_to_wp);
3901     }
3902
3903     /* Set gc_alloc() back to generation 0. The current regions should
3904      * be flushed after the above GCs. */
3905     gc_assert((boxed_region.free_pointer - boxed_region.start_addr) == 0);
3906     gc_alloc_generation = 0;
3907
3908     update_dynamic_space_free_pointer();
3909     auto_gc_trigger = bytes_allocated + bytes_consed_between_gcs;
3910     if(gencgc_verbose)
3911         fprintf(stderr,"Next gc when %ld bytes have been consed\n",
3912                 auto_gc_trigger);
3913     SHOW("returning from collect_garbage");
3914 }
3915
3916 /* This is called by Lisp PURIFY when it is finished. All live objects
3917  * will have been moved to the RO and Static heaps. The dynamic space
3918  * will need a full re-initialization. We don't bother having Lisp
3919  * PURIFY flush the current gc_alloc() region, as the page_tables are
3920  * re-initialized, and every page is zeroed to be sure. */
3921 void
3922 gc_free_heap(void)
3923 {
3924     page_index_t page;
3925
3926     if (gencgc_verbose > 1)
3927         SHOW("entering gc_free_heap");
3928
3929     for (page = 0; page < NUM_PAGES; page++) {
3930         /* Skip free pages which should already be zero filled. */
3931         if (page_table[page].allocated != FREE_PAGE_FLAG) {
3932             void *page_start, *addr;
3933
3934             /* Mark the page free. The other slots are assumed invalid
3935              * when it is a FREE_PAGE_FLAG and bytes_used is 0 and it
3936              * should not be write-protected -- except that the
3937              * generation is used for the current region but it sets
3938              * that up. */
3939             page_table[page].allocated = FREE_PAGE_FLAG;
3940             page_table[page].bytes_used = 0;
3941
3942             /* Zero the page. */
3943             page_start = (void *)page_address(page);
3944
3945             /* First, remove any write-protection. */
3946             os_protect(page_start, PAGE_BYTES, OS_VM_PROT_ALL);
3947             page_table[page].write_protected = 0;
3948
3949             os_invalidate(page_start,PAGE_BYTES);
3950             addr = os_validate(page_start,PAGE_BYTES);
3951             if (addr == NULL || addr != page_start) {
3952                 lose("gc_free_heap: page moved, 0x%08x ==> 0x%08x",
3953                      page_start,
3954                      addr);
3955             }
3956         } else if (gencgc_zero_check_during_free_heap) {
3957             /* Double-check that the page is zero filled. */
3958             long *page_start;
3959             page_index_t i;
3960             gc_assert(page_table[page].allocated == FREE_PAGE_FLAG);
3961             gc_assert(page_table[page].bytes_used == 0);
3962             page_start = (long *)page_address(page);
3963             for (i=0; i<1024; i++) {
3964                 if (page_start[i] != 0) {
3965                     lose("free region not zero at %x", page_start + i);
3966                 }
3967             }
3968         }
3969     }
3970
3971     bytes_allocated = 0;
3972
3973     /* Initialize the generations. */
3974     for (page = 0; page < NUM_GENERATIONS; page++) {
3975         generations[page].alloc_start_page = 0;
3976         generations[page].alloc_unboxed_start_page = 0;
3977         generations[page].alloc_large_start_page = 0;
3978         generations[page].alloc_large_unboxed_start_page = 0;
3979         generations[page].bytes_allocated = 0;
3980         generations[page].gc_trigger = 2000000;
3981         generations[page].num_gc = 0;
3982         generations[page].cum_sum_bytes_allocated = 0;
3983     }
3984
3985     if (gencgc_verbose > 1)
3986         print_generation_stats(0);
3987
3988     /* Initialize gc_alloc(). */
3989     gc_alloc_generation = 0;
3990
3991     gc_set_region_empty(&boxed_region);
3992     gc_set_region_empty(&unboxed_region);
3993
3994     last_free_page = 0;
3995     SetSymbolValue(ALLOCATION_POINTER, (lispobj)((char *)heap_base),0);
3996
3997     if (verify_after_free_heap) {
3998         /* Check whether purify has left any bad pointers. */
3999         if (gencgc_verbose)
4000             SHOW("checking after free_heap\n");
4001         verify_gc();
4002     }
4003 }
4004 \f
4005 void
4006 gc_init(void)
4007 {
4008     page_index_t i;
4009
4010     gc_init_tables();
4011     scavtab[SIMPLE_VECTOR_WIDETAG] = scav_vector;
4012     scavtab[WEAK_POINTER_WIDETAG] = scav_weak_pointer;
4013     transother[SIMPLE_ARRAY_WIDETAG] = trans_boxed_large;
4014
4015     heap_base = (void*)DYNAMIC_SPACE_START;
4016
4017     /* Initialize each page structure. */
4018     for (i = 0; i < NUM_PAGES; i++) {
4019         /* Initialize all pages as free. */
4020         page_table[i].allocated = FREE_PAGE_FLAG;
4021         page_table[i].bytes_used = 0;
4022
4023         /* Pages are not write-protected at startup. */
4024         page_table[i].write_protected = 0;
4025     }
4026
4027     bytes_allocated = 0;
4028
4029     /* Initialize the generations.
4030      *
4031      * FIXME: very similar to code in gc_free_heap(), should be shared */
4032     for (i = 0; i < NUM_GENERATIONS; i++) {
4033         generations[i].alloc_start_page = 0;
4034         generations[i].alloc_unboxed_start_page = 0;
4035         generations[i].alloc_large_start_page = 0;
4036         generations[i].alloc_large_unboxed_start_page = 0;
4037         generations[i].bytes_allocated = 0;
4038         generations[i].gc_trigger = 2000000;
4039         generations[i].num_gc = 0;
4040         generations[i].cum_sum_bytes_allocated = 0;
4041         /* the tune-able parameters */
4042         generations[i].bytes_consed_between_gc = 2000000;
4043         generations[i].trigger_age = 1;
4044         generations[i].min_av_mem_age = 0.75;
4045     }
4046
4047     /* Initialize gc_alloc. */
4048     gc_alloc_generation = 0;
4049     gc_set_region_empty(&boxed_region);
4050     gc_set_region_empty(&unboxed_region);
4051
4052     last_free_page = 0;
4053
4054 }
4055
4056 /*  Pick up the dynamic space from after a core load.
4057  *
4058  *  The ALLOCATION_POINTER points to the end of the dynamic space.
4059  */
4060
4061 static void
4062 gencgc_pickup_dynamic(void)
4063 {
4064     page_index_t page = 0;
4065     long alloc_ptr = SymbolValue(ALLOCATION_POINTER,0);
4066     lispobj *prev=(lispobj *)page_address(page);
4067
4068     do {
4069         lispobj *first,*ptr= (lispobj *)page_address(page);
4070         page_table[page].allocated = BOXED_PAGE_FLAG;
4071         page_table[page].gen = 0;
4072         page_table[page].bytes_used = PAGE_BYTES;
4073         page_table[page].large_object = 0;
4074
4075         first=gc_search_space(prev,(ptr+2)-prev,ptr);
4076         if(ptr == first)  prev=ptr;
4077         page_table[page].first_object_offset =
4078             (void *)prev - page_address(page);
4079         page++;
4080     } while ((long)page_address(page) < alloc_ptr);
4081
4082     generations[0].bytes_allocated = PAGE_BYTES*page;
4083     bytes_allocated = PAGE_BYTES*page;
4084
4085 }
4086
4087 void
4088 gc_initialize_pointers(void)
4089 {
4090     gencgc_pickup_dynamic();
4091 }
4092
4093
4094 \f
4095
4096 /* alloc(..) is the external interface for memory allocation. It
4097  * allocates to generation 0. It is not called from within the garbage
4098  * collector as it is only external uses that need the check for heap
4099  * size (GC trigger) and to disable the interrupts (interrupts are
4100  * always disabled during a GC).
4101  *
4102  * The vops that call alloc(..) assume that the returned space is zero-filled.
4103  * (E.g. the most significant word of a 2-word bignum in MOVE-FROM-UNSIGNED.)
4104  *
4105  * The check for a GC trigger is only performed when the current
4106  * region is full, so in most cases it's not needed. */
4107
4108 char *
4109 alloc(long nbytes)
4110 {
4111     struct thread *thread=arch_os_get_current_thread();
4112     struct alloc_region *region=
4113 #ifdef LISP_FEATURE_SB_THREAD
4114         thread ? &(thread->alloc_region) : &boxed_region;
4115 #else
4116         &boxed_region;
4117 #endif
4118     void *new_obj;
4119     void *new_free_pointer;
4120     gc_assert(nbytes>0);
4121     /* Check for alignment allocation problems. */
4122     gc_assert((((unsigned long)region->free_pointer & LOWTAG_MASK) == 0)
4123               && ((nbytes & LOWTAG_MASK) == 0));
4124 #if 0
4125     if(all_threads)
4126         /* there are a few places in the C code that allocate data in the
4127          * heap before Lisp starts.  This is before interrupts are enabled,
4128          * so we don't need to check for pseudo-atomic */
4129 #ifdef LISP_FEATURE_SB_THREAD
4130         if(!SymbolValue(PSEUDO_ATOMIC_ATOMIC,th)) {
4131             register u32 fs;
4132             fprintf(stderr, "fatal error in thread 0x%x, tid=%ld\n",
4133                     th,th->os_thread);
4134             __asm__("movl %fs,%0" : "=r" (fs)  : );
4135             fprintf(stderr, "fs is %x, th->tls_cookie=%x \n",
4136                     debug_get_fs(),th->tls_cookie);
4137             lose("If you see this message before 2004.01.31, mail details to sbcl-devel\n");
4138         }
4139 #else
4140     gc_assert(SymbolValue(PSEUDO_ATOMIC_ATOMIC,th));
4141 #endif
4142 #endif
4143
4144     /* maybe we can do this quickly ... */
4145     new_free_pointer = region->free_pointer + nbytes;
4146     if (new_free_pointer <= region->end_addr) {
4147         new_obj = (void*)(region->free_pointer);
4148         region->free_pointer = new_free_pointer;
4149         return(new_obj);        /* yup */
4150     }
4151
4152     /* we have to go the long way around, it seems.  Check whether
4153      * we should GC in the near future
4154      */
4155     if (auto_gc_trigger && bytes_allocated > auto_gc_trigger) {
4156         gc_assert(fixnum_value(SymbolValue(PSEUDO_ATOMIC_ATOMIC,thread)));
4157         /* Don't flood the system with interrupts if the need to gc is
4158          * already noted. This can happen for example when SUB-GC
4159          * allocates or after a gc triggered in a WITHOUT-GCING. */
4160         if (SymbolValue(GC_PENDING,thread) == NIL) {
4161             /* set things up so that GC happens when we finish the PA
4162              * section */
4163             SetSymbolValue(GC_PENDING,T,thread);
4164             if (SymbolValue(GC_INHIBIT,thread) == NIL)
4165                 arch_set_pseudo_atomic_interrupted(0);
4166         }
4167     }
4168     new_obj = gc_alloc_with_region(nbytes,0,region,0);
4169     return (new_obj);
4170 }
4171 \f
4172 /*
4173  * shared support for the OS-dependent signal handlers which
4174  * catch GENCGC-related write-protect violations
4175  */
4176
4177 void unhandled_sigmemoryfault(void);
4178
4179 /* Depending on which OS we're running under, different signals might
4180  * be raised for a violation of write protection in the heap. This
4181  * function factors out the common generational GC magic which needs
4182  * to invoked in this case, and should be called from whatever signal
4183  * handler is appropriate for the OS we're running under.
4184  *
4185  * Return true if this signal is a normal generational GC thing that
4186  * we were able to handle, or false if it was abnormal and control
4187  * should fall through to the general SIGSEGV/SIGBUS/whatever logic. */
4188
4189 int
4190 gencgc_handle_wp_violation(void* fault_addr)
4191 {
4192     page_index_t page_index = find_page_index(fault_addr);
4193
4194 #ifdef QSHOW_SIGNALS
4195     FSHOW((stderr, "heap WP violation? fault_addr=%x, page_index=%d\n",
4196            fault_addr, page_index));
4197 #endif
4198
4199     /* Check whether the fault is within the dynamic space. */
4200     if (page_index == (-1)) {
4201
4202         /* It can be helpful to be able to put a breakpoint on this
4203          * case to help diagnose low-level problems. */
4204         unhandled_sigmemoryfault();
4205
4206         /* not within the dynamic space -- not our responsibility */
4207         return 0;
4208
4209     } else {
4210         if (page_table[page_index].write_protected) {
4211             /* Unprotect the page. */
4212             os_protect(page_address(page_index), PAGE_BYTES, OS_VM_PROT_ALL);
4213             page_table[page_index].write_protected_cleared = 1;
4214             page_table[page_index].write_protected = 0;
4215         } else {
4216             /* The only acceptable reason for this signal on a heap
4217              * access is that GENCGC write-protected the page.
4218              * However, if two CPUs hit a wp page near-simultaneously,
4219              * we had better not have the second one lose here if it
4220              * does this test after the first one has already set wp=0
4221              */
4222             if(page_table[page_index].write_protected_cleared != 1)
4223                 lose("fault in heap page not marked as write-protected");
4224         }
4225         /* Don't worry, we can handle it. */
4226         return 1;
4227     }
4228 }
4229 /* This is to be called when we catch a SIGSEGV/SIGBUS, determine that
4230  * it's not just a case of the program hitting the write barrier, and
4231  * are about to let Lisp deal with it. It's basically just a
4232  * convenient place to set a gdb breakpoint. */
4233 void
4234 unhandled_sigmemoryfault()
4235 {}
4236
4237 void gc_alloc_update_all_page_tables(void)
4238 {
4239     /* Flush the alloc regions updating the tables. */
4240     struct thread *th;
4241     for_each_thread(th)
4242         gc_alloc_update_page_tables(0, &th->alloc_region);
4243     gc_alloc_update_page_tables(1, &unboxed_region);
4244     gc_alloc_update_page_tables(0, &boxed_region);
4245 }
4246
4247 void
4248 gc_set_region_empty(struct alloc_region *region)
4249 {
4250     region->first_page = 0;
4251     region->last_page = -1;
4252     region->start_addr = page_address(0);
4253     region->free_pointer = page_address(0);
4254     region->end_addr = page_address(0);
4255 }
4256