2 * This software is part of the SBCL system. See the README file for
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
13 #include "gc-internal.h"
14 #include "gc-private.h"
15 #include "genesis/gc-tables.h"
16 #include "genesis/closure.h"
17 #include "genesis/layout.h"
18 #include "genesis/hash-table.h"
22 #ifndef LISP_FEATURE_WIN32
23 #define HAVE_GETRUSAGE 1
26 #include <sys/resource.h> // for getrusage()
30 /* Most headered objects use MARK_BIT to record liveness.
31 * Bignums always use the leftmost bit regardless of word size */
32 #define MARK_BIT ((uword_t)1 << 31)
33 #ifdef LISP_FEATURE_64_BIT
34 #define BIGNUM_MARK_BIT ((uword_t)1 << 63)
36 #define BIGNUM_MARK_BIT MARK_BIT
39 #define interesting_pointer_p(x) \
40 (find_page_index((void*)x) >= 0 || immobile_space_p(x))
43 # define dprintf(arg) printf arg
49 struct unbounded_queue
{
50 struct Qblock
* head_block
;
51 struct Qblock
* tail_block
;
52 struct Qblock
* recycler
;
53 long tot_count
; // Not used
56 /* Initialized to number of pages in page table
57 * and decremented before use. */
58 static page_index_t free_page
;
60 /* The whole-page allocator works backwards from the end of dynamic space.
61 * If it collides with 'last_free_page', then you lose. */
62 static void* get_free_page() {
64 if (free_page
< last_free_page
)
65 lose("Needed more space to GC\n");
66 char* mem
= page_address(free_page
);
67 if (page_need_to_zero(free_page
))
68 memset(mem
, 0, GENCGC_CARD_BYTES
);
69 set_page_need_to_zero(free_page
, 1);
73 /* The suballocator doles out blocks of bits for marking conses live.
74 * Example: If pages are 32768 bytes, and Lisp words are 8 bytes,
75 * then one GC page can hold 2K cons cells.
76 * One byte marks 8 conses (1 bit per cons), 256 bytes mark 2048 conses.
77 * 128 blocks of 256 bytes fit on a 32K GC page. */
78 char *suballocator_free_ptr
, *suballocator_end_ptr
;
80 static void* allocate_cons_mark_bits() {
81 int nbytes
= GENCGC_CARD_BYTES
/ (2 * N_WORD_BYTES
) / 8;
82 if (suballocator_free_ptr
+ nbytes
> suballocator_end_ptr
) {
83 suballocator_free_ptr
= get_free_page();
84 suballocator_end_ptr
= suballocator_free_ptr
+ GENCGC_CARD_BYTES
;
86 void* mem
= suballocator_free_ptr
;
87 suballocator_free_ptr
+= nbytes
;
91 static void gc_enqueue(lispobj object
)
93 gc_dcheck(is_lisp_pointer(object
));
94 struct Qblock
* block
= scav_queue
.tail_block
;
95 if (block
->count
== QBLOCK_CAPACITY
) {
97 next
= scav_queue
.recycler
;
99 scav_queue
.recycler
= next
->next
;
101 dprintf(("Popped recycle list\n"));
103 next
= (struct Qblock
*)get_free_page();
104 dprintf(("Alloc'd new block\n"));
106 block
= block
->next
= next
;
107 scav_queue
.tail_block
= block
;
109 block
->elements
[block
->tail
] = object
;
110 if (++block
->tail
== QBLOCK_CAPACITY
) block
->tail
= 0;
114 static lispobj
gc_dequeue()
116 struct Qblock
* block
= scav_queue
.head_block
;
117 gc_assert(block
->count
);
118 int index
= block
->tail
- block
->count
;
119 lispobj object
= block
->elements
[index
+ (index
<0 ? QBLOCK_CAPACITY
: 0)];
120 if (--block
->count
== 0) {
121 struct Qblock
* next
= block
->next
;
123 scav_queue
.head_block
= next
;
124 block
->next
= scav_queue
.recycler
;
125 scav_queue
.recycler
= block
;
126 dprintf(("Qblock emptied - returned to recycle list\n"));
128 dprintf(("Qblock emptied - NOT returned to recycle list\n"));
134 /* The 'mark_bits' hashtable maps a page address to a block of mark bits
135 * for headerless objects (conses) */
136 struct hopscotch_table mark_bits
;
138 static inline uword_t
compute_page_key(lispobj cons
) {
139 return ALIGN_DOWN(cons
, GENCGC_CARD_BYTES
);
141 static inline int compute_dword_number(lispobj cons
) {
142 return (cons
& (GENCGC_CARD_BYTES
- 1)) >> (1+WORD_SHIFT
);
145 static inline int cons_markedp(lispobj pointer
) {
146 unsigned char* bits
= (unsigned char*)
147 hopscotch_get(&mark_bits
, compute_page_key(pointer
), 0);
149 int index
= compute_dword_number(pointer
);
150 return (bits
[index
/ 8] >> (index
% 8)) & 1;
153 #ifdef RETURN_PC_WIDETAG
154 #define embedded_obj_p(tag) tag==RETURN_PC_WIDETAG || tag==SIMPLE_FUN_WIDETAG
156 #define embedded_obj_p(tag) tag==SIMPLE_FUN_WIDETAG
159 /* Return true if OBJ has already survived the current GC. */
160 static inline int pointer_survived_gc_yet(lispobj pointer
)
162 if (!interesting_pointer_p(pointer
))
164 if (lowtag_of(pointer
) == LIST_POINTER_LOWTAG
)
165 return cons_markedp(pointer
);
166 lispobj header
= *native_pointer(pointer
);
167 if (widetag_of(header
) == BIGNUM_WIDETAG
)
168 return (header
& BIGNUM_MARK_BIT
) != 0;
169 if (embedded_obj_p(widetag_of(header
)))
170 header
= *fun_code_header(native_pointer(pointer
));
171 return (header
& MARK_BIT
) != 0;
174 void __mark_obj(lispobj pointer
)
176 gc_dcheck(is_lisp_pointer(pointer
));
177 if (!interesting_pointer_p(pointer
))
179 if (lowtag_of(pointer
) != LIST_POINTER_LOWTAG
) {
180 lispobj
* base
= native_pointer(pointer
);
181 lispobj header
= *base
;
182 if (widetag_of(header
) == BIGNUM_WIDETAG
) {
183 *base
|= BIGNUM_MARK_BIT
;
184 return; // don't enqueue - no pointers
186 if (embedded_obj_p(widetag_of(header
))) {
187 base
= fun_code_header(base
);
188 pointer
= make_lispobj(base
, OTHER_POINTER_LOWTAG
);
191 // Bit 31 of the header is the mark bit for all remaining object types.
192 // This avoids clash with the layout pointer of instances and functions,
193 // TLS index of symbols, and various other bits.
194 // The mark bit occupies the same byte as the generation number
195 // in immobile space, but doesn't conflict with that usage.
196 if (header
& MARK_BIT
)
197 return; // already marked
200 if (unboxed_obj_widetag_p(widetag_of(header
)))
203 uword_t key
= compute_page_key(pointer
);
204 int index
= compute_dword_number(pointer
);
205 unsigned char* bits
= (unsigned char*)hopscotch_get(&mark_bits
, key
, 0);
207 bits
= allocate_cons_mark_bits();
208 hopscotch_insert(&mark_bits
, key
, (sword_t
)bits
);
209 } else if (bits
[index
/ 8] & (1 << (index
% 8))) {
213 bits
[index
/ 8] |= 1 << (index
% 8);
218 inline void gc_mark_obj(lispobj thing
) {
219 if (is_lisp_pointer(thing
))
223 static inline void mark_pair(lispobj
* where
)
225 gc_mark_obj(where
[0]);
226 gc_mark_obj(where
[1]);
229 void gc_mark_range(lispobj
* where
, long count
) {
231 for(i
=0; i
<count
; ++i
)
232 gc_mark_obj(where
[i
]);
235 #define HT_ENTRY_LIVENESS_FUN_ARRAY_NAME alivep_funs
236 #include "weak-hash-pred.inc"
238 static void trace_object(lispobj
* where
)
240 lispobj header
= *where
;
241 int widetag
= widetag_of(header
);
242 sword_t scan_from
= 1;
243 sword_t scan_to
= sizetab
[widetag
](where
);
245 struct weak_pointer
*weakptr
;
246 lispobj layout
, bitmap
;
248 /* If the C compiler emits this switch as a jump table, order doesn't matter.
249 * But if as consecutive tests, instance and vector should be tested first
250 * as they are the most freequent */
252 case INSTANCE_WIDETAG
:
253 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
254 /* No need to deal with FINs for non-compact header, because the layout
255 pointer isn't in the header word, the trampoline pointer can only point
256 to readonly space, and all slots are tagged. */
257 case FUNCALLABLE_INSTANCE_WIDETAG
:
258 layout
= instance_layout(where
);
261 layout
= instance_layout(where
); // will be marked as where[1]
263 if (!layout
) break; // fall into general case
264 // mixed boxed/unboxed objects
265 bitmap
= ((struct layout
*)native_pointer(layout
))->bitmap
;
266 // If no raw slots, just scan without use of the bitmap.
267 if (bitmap
== make_fixnum(-1)) break;
268 for(i
=1; i
<scan_to
; ++i
)
269 if (layout_bitmap_logbitp(i
-1, bitmap
) && is_lisp_pointer(where
[i
]))
270 __mark_obj(where
[i
]);
271 return; // do not scan slots
272 case SIMPLE_VECTOR_WIDETAG
:
273 if (is_vector_subtype(header
, VectorValidHashing
)) {
274 lispobj lhash_table
= where
[2];
275 gc_dcheck(is_lisp_pointer(lhash_table
));
276 __mark_obj(lhash_table
);
277 struct hash_table
* hash_table
278 = (struct hash_table
*)native_pointer(lhash_table
);
279 if (!hash_table
->_weakness
) {
280 scav_hash_table_entries(hash_table
, alivep_funs
, mark_pair
);
282 // An object can only be removed from the queue once.
283 // Therefore the 'next' pointer has got to be nil.
284 gc_assert(hash_table
->next_weak_hash_table
== NIL
);
285 hash_table
->next_weak_hash_table
= (lispobj
)weak_hash_tables
;
286 weak_hash_tables
= hash_table
;
291 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
292 /* on x86[-64], closure->fun is a fixnum-qua-pointer. Convert it to a lisp
293 * pointer to mark it, but not on platforms where it's already a descriptor */
294 case CLOSURE_WIDETAG
:
295 gc_mark_obj(((struct closure
*)where
)->fun
- FUN_RAW_ADDR_OFFSET
);
297 break; // scan slots normally
299 case CODE_HEADER_WIDETAG
:
300 for_each_simple_fun(i
, fun
, (struct code
*)where
, 0, {
301 gc_mark_range(SIMPLE_FUN_SCAV_START(fun
),
302 SIMPLE_FUN_SCAV_NWORDS(fun
));
304 scan_to
= code_header_words(header
);
307 gc_mark_obj(fdefn_callee_lispobj((struct fdefn
*)where
));
310 case WEAK_POINTER_WIDETAG
:
311 weakptr
= (struct weak_pointer
*)where
;
312 if (is_lisp_pointer(weakptr
->value
) && interesting_pointer_p(weakptr
->value
))
313 add_to_weak_pointer_list(weakptr
);
316 if (unboxed_obj_widetag_p(widetag
)) return;
318 for(i
=scan_from
; i
<scan_to
; ++i
)
319 gc_mark_obj(where
[i
]);
322 void prepare_for_full_mark_phase()
324 // FIXME: Estimate how large to create mark_bits based on dynamic space size.
325 // Guess 8 words per object, and X% of the objects are conses.
326 // The problem is guessing how localized the conses are: guess that N conses
327 // will reside on fraction*N different pages, which guides us as to how many
328 // hash table entries are needed.
329 hopscotch_create(&mark_bits
, HOPSCOTCH_HASH_FUN_DEFAULT
,
330 N_WORD_BYTES
, /* table values are machine words */
331 65536, /* initial size */
334 free_page
= page_table_pages
;
335 suballocator_free_ptr
= suballocator_end_ptr
= 0;
336 struct Qblock
* block
= (struct Qblock
*)get_free_page();
337 dprintf(("Queue block holds %d objects\n", (int)QBLOCK_CAPACITY
));
338 scav_queue
.head_block
= block
;
339 scav_queue
.tail_block
= block
;
340 scav_queue
.recycler
= 0;
341 gc_assert(!scav_queue
.head_block
->count
);
344 void execute_full_mark_phase()
347 struct rusage before
, after
;
348 getrusage(RUSAGE_SELF
, &before
);
350 lispobj
* where
= (lispobj
*)STATIC_SPACE_START
;
351 lispobj
* end
= static_space_free_pointer
;
352 while (where
< end
) {
353 lispobj obj
= compute_lispobj(where
);
355 where
+= lowtag_of(obj
) != LIST_POINTER_LOWTAG
356 ? sizetab
[widetag_of(*where
)](where
) : 2;
359 while (scav_queue
.head_block
->count
) {
360 lispobj ptr
= gc_dequeue();
362 if (lowtag_of(ptr
) != LIST_POINTER_LOWTAG
)
363 trace_object(native_pointer(ptr
));
365 mark_pair((lispobj
*)(ptr
- LIST_POINTER_LOWTAG
));
367 if (weak_hash_tables
) {
368 scav_weak_hash_tables(alivep_funs
, mark_pair
);
369 if (scav_queue
.head_block
->count
) {
370 dprintf(("looping due to weak objects\n"));
375 getrusage(RUSAGE_SELF
, &after
);
376 #define timediff(b,a,field) \
377 (double)((a.field.tv_sec-b.field.tv_sec)*1000000 + \
378 (a.field.tv_usec-b.field.tv_usec)) / 1000000.0
381 "[Mark phase: %d pages used, HT-count=%d, ET=%f+%f sys+usr]\n",
382 (int)(page_table_pages
- free_page
), mark_bits
.count
,
383 timediff(before
, after
, ru_stime
), timediff(before
, after
, ru_utime
));
387 static void smash_weak_pointers()
389 struct weak_pointer
*wp
, *next_wp
;
390 for (wp
= weak_pointers
, next_wp
= NULL
; wp
!= NULL
; wp
= next_wp
) {
391 gc_assert(widetag_of(wp
->header
)==WEAK_POINTER_WIDETAG
);
395 if (next_wp
== wp
) /* gencgc uses a ref to self for end of list */
398 lispobj pointee
= wp
->value
;
399 gc_assert(is_lisp_pointer(pointee
));
400 if (!pointer_survived_gc_yet(pointee
))
401 wp
->value
= UNBOUND_MARKER_WIDETAG
;
405 __attribute__((unused
)) static char *fillerp(lispobj
* where
)
408 if (where
[0] | where
[1])
410 if ((page
= find_page_index(where
)) >= 0 && page_table
[page
].large_object
)
411 return "cons (largeobj filler)";
412 return "cons (filler)";
417 #ifdef LOG_SWEEP_ACTIONS
418 # define NOTE_GARBAGE(gen,addr,nwords,tally) \
419 { tally[gen] += nwords; \
421 fprintf(sweeplog, "%5d %d #x%"OBJ_FMTX": %"OBJ_FMTX" %"OBJ_FMTX"\n", \
422 (int)nwords, gen, compute_lispobj(addr), \
425 # define NOTE_GARBAGE(gen,addr,nwords,tally) tally[gen] += nwords
428 #ifndef LISP_FEATURE_IMMOBILE_SPACE
429 #define __immobile_obj_gen_bits(x) (lose("No page index?"),0)
431 static void sweep_fixedobj_pages(long *zeroed
)
433 low_page_index_t page
;
435 for (page
= 0 ; ; ++page
) {
436 lispobj
*obj
= (lispobj
*)((char*)IMMOBILE_SPACE_START
+ page
* IMMOBILE_CARD_BYTES
);
437 if (obj
>= immobile_fixedobj_free_pointer
)
439 int obj_spacing
= fixedobj_page_obj_align(page
);
442 int nwords
= fixedobj_page_obj_size(page
);
443 lispobj
*limit
= (lispobj
*)((char*)obj
+ IMMOBILE_CARD_BYTES
- obj_spacing
);
444 for ( ; obj
<= limit
; obj
= (lispobj
*)((char*)obj
+ obj_spacing
) ) {
445 lispobj header
= *obj
;
446 if (fixnump(header
)) { // is a hole
447 } else if (header
& MARK_BIT
) { // live object
448 *obj
= header
^ MARK_BIT
;
450 NOTE_GARBAGE(__immobile_obj_gen_bits(obj
), obj
, nwords
, zeroed
);
451 memset(obj
, 0, nwords
* N_WORD_BYTES
);
458 static uword_t
sweep(lispobj
* where
, lispobj
* end
, uword_t arg
)
460 long *zeroed
= (long*)arg
; // one count per generation
463 // TODO: consecutive dead objects on same page should be merged.
464 for ( ; where
< end
; where
+= nwords
) {
465 lispobj header
= *where
;
466 if (is_cons_half(header
)) {
468 if (!cons_markedp((lispobj
)where
)) {
469 if (where
[0] | where
[1]) {
471 gc_dcheck(!immobile_space_p((lispobj
)where
));
472 NOTE_GARBAGE(page_table
[find_page_index(where
)].gen
,
474 where
[0] = where
[1] = 0;
478 nwords
= sizetab
[widetag_of(header
)](where
);
480 widetag_of(header
) != BIGNUM_WIDETAG
? MARK_BIT
: BIGNUM_MARK_BIT
;
481 if (header
& markbit
)
482 *where
= header
^ markbit
;
484 // Turn the object into either a (0 . 0) cons
485 // or an unboxed filler depending on size.
486 if (nwords
<= 2) // could be SAP, SIMPLE-ARRAY-NIL, 1-word bignum, etc
488 struct code
* code
= (struct code
*)where
;
489 lispobj header
= 2<<N_WIDETAG_BITS
| CODE_HEADER_WIDETAG
;
490 if (code
->header
!= header
) {
491 page_index_t page
= find_page_index(where
);
492 int gen
= page
>= 0 ? page_table
[page
].gen
493 : __immobile_obj_gen_bits(where
);
494 NOTE_GARBAGE(gen
, where
, nwords
, zeroed
);
495 code
->header
= header
;
496 code
->code_size
= make_fixnum((nwords
- 2) * N_WORD_BYTES
);
497 memset(where
+2, 0, (nwords
- 2) * N_WORD_BYTES
);
505 void execute_full_sweep_phase()
507 long words_zeroed
[1+PSEUDO_STATIC_GENERATION
]; // One count per generation
509 scan_weak_hash_tables(alivep_funs
);
510 smash_weak_pointers();
512 #ifdef LOG_SWEEP_ACTIONS
513 sweeplog
= fopen("/tmp/sweep.log", "a");
514 fprintf(sweeplog
, "-- begin sweep --\n");
517 memset(words_zeroed
, 0, sizeof words_zeroed
);
518 #ifdef LISP_FEATURE_IMMOBILE_SPACE
519 sweep_fixedobj_pages(words_zeroed
);
520 if (sweeplog
) fprintf(sweeplog
, "-- varyobj pages --\n");
521 sweep((lispobj
*)IMMOBILE_VARYOBJ_SUBSPACE_START
, immobile_space_free_pointer
,
522 (uword_t
)words_zeroed
);
524 if (sweeplog
) fprintf(sweeplog
, "-- dynamic space --\n");
525 walk_generation(sweep
, -1, (uword_t
)words_zeroed
);
526 if (gencgc_verbose
) {
527 fprintf(stderr
, "[Sweep phase: ");
530 fprintf(stderr
, "%ld%s", words_zeroed
[i
], i
?"+":"");
531 fprintf(stderr
, " words zeroed]\n");
533 hopscotch_destroy(&mark_bits
);
534 #ifdef LOG_SWEEP_ACTIONS
539 page_index_t first_page
, last_page
;
540 for (first_page
= 0; first_page
< last_free_page
; ++first_page
)
541 if (page_table
[first_page
].write_protected
) {
542 last_page
= first_page
;
543 while (page_table
[last_page
+1].write_protected
)
545 os_protect(page_address(first_page
),
546 (last_page
- first_page
+ 1) * GENCGC_CARD_BYTES
,
547 OS_VM_PROT_READ
| OS_VM_PROT_EXECUTE
);
548 first_page
= last_page
;