Use defglobal less
[sbcl.git] / src / runtime / marknsweepgc.c
blob61bc7854960be719d1ef8f4cc77f2f09b65eed86
1 /*
2 * Extension to GENCGC which provides for pages of objects
3 * that are static in placement but subject to reclamation.
4 */
6 /*
7 * This software is part of the SBCL system. See the README file for
8 * more information.
10 * This software is derived from the CMU CL system, which was
11 * written at Carnegie Mellon University and released into the
12 * public domain. The software is in the public domain and is
13 * provided with absolutely no warranty. See the COPYING and CREDITS
14 * files for more information.
18 * TODO:
19 * 1. Space accounting (GET-BYTES-CONSED etc)
20 * 2. Heuristic for auto-trigger. (Can't yet because no space accounting)
21 * Currently happens with regular GC trigger mechanism.
22 * 3. Specify space size on startup
25 // Work around a bug in some llvm/clang versions affecting the memcpy
26 // call in defrag_immobile_space:
28 // When compiled with _FORTIFY_SOURCE nonzero, as seems to be the
29 // default, memcpy is a macro that expands to
30 // __builtin_memcpy_chk(dst, source, size, __builtin_object_size(...)).
32 // Now usually if the compiler knows that it does not know
33 // __builtin_object_size for the source of the copy, the
34 // __builtin_memcpy_chk call becomes plain old memcpy. But in the
35 // buggy case, the compiler is convinced that it does know the
36 // size. This shows up clearly in the disassembly, where the library
37 // routine receives a source size that was erroneously determined to
38 // be a compile-time constant 0. Thus the assertion failure is that
39 // you are reading from a range with 0 bytes in it.
41 // Defining _FORTIFY_LEVEL 0 disables the above macro and thus works
42 // around the problem. Since it is unclear which clang versions are
43 // affected, only apply the workaround for the known-bad version.
44 #if (defined(__clang__) && (__clang_major__ == 6) && (__clang_minor__ == 0))
45 #define _FORTIFY_SOURCE 0
46 #endif
48 #include "gc.h"
49 #include "gc-internal.h"
50 #include "genesis/gc-tables.h"
51 #include "genesis/vector.h"
52 #include "forwarding-ptr.h"
53 #include "pseudo-atomic.h"
54 #include "var-io.h"
56 #include <stdlib.h>
57 #include <stdio.h>
59 #define FIRST_VARYOBJ_PAGE (IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE/(int)IMMOBILE_CARD_BYTES)
60 #define WORDS_PER_PAGE ((int)IMMOBILE_CARD_BYTES/N_WORD_BYTES)
61 #define DOUBLEWORDS_PER_PAGE (WORDS_PER_PAGE/2)
63 // In case of problems while debugging, this is selectable.
64 #define DEFRAGMENT_FIXEDOBJ_SUBSPACE 1
66 #undef DEBUG
67 #undef VERIFY_PAGE_GENS
69 #ifdef DEBUG
70 # define dprintf(arg) fprintf arg
71 FILE * logfile;
72 #else
73 # define dprintf(arg)
74 #endif
76 unsigned ASM_ROUTINES_END;
78 // Inclusive bounds on highest in-use pages per subspace.
79 low_page_index_t max_used_fixedobj_page, max_used_varyobj_page;
81 // This table is for objects fixed in size, as opposed to variable-sized.
82 // (Immobile objects are naturally fixed in placement)
83 struct fixedobj_page { // 12 bytes per page
84 union immobile_page_attr {
85 int packed;
86 struct {
87 unsigned char flags;
88 /* space per object in Lisp words. Can exceed obj_size
89 to align on a larger boundary */
90 unsigned char obj_align;
91 unsigned char obj_size; /* in Lisp words, incl. header */
92 /* Which generations have data on this page */
93 unsigned char gens_; // a bitmap
94 } parts;
95 } attr;
96 int free_index; // index is in bytes. 4 bytes
97 short int prior_gc_free_word_index; // index is in words. 2 bytes
98 /* page index of next page with same attributes */
99 short int page_link; // 2 bytes
100 } *fixedobj_pages;
102 unsigned int* immobile_scav_queue;
103 int immobile_scav_queue_head;
104 // Number of items enqueued; can exceed QCAPACITY on overflow.
105 // If overflowed, the queue is unusable until reset.
106 unsigned int immobile_scav_queue_count;
107 #define QCAPACITY (IMMOBILE_CARD_BYTES/sizeof(int))
109 #define gens attr.parts.gens_
111 // These are the high 2 bits of 'flags'
112 #define WRITE_PROTECT 0x80
113 #define WRITE_PROTECT_CLEARED 0x40
115 // Packing and unpacking attributes
116 // the low two flag bits are for write-protect status
117 #define MAKE_ATTR(spacing,size,flags) (((spacing)<<8)|((size)<<16)|flags)
118 #define OBJ_SPACING(attr) ((attr>>8) & 0xFF)
120 // Ignore the write-protect bits and the generations when comparing attributes
121 #define ATTRIBUTES_MATCH_P(page_attr,specified_attr) \
122 ((page_attr & 0xFFFF3F) == specified_attr)
123 #define SET_WP_FLAG(index,flag) \
124 fixedobj_pages[index].attr.parts.flags = (fixedobj_pages[index].attr.parts.flags & 0x3F) | flag
126 #define page_obj_align(i) fixedobj_pages[i].attr.parts.obj_align
127 #define page_obj_size(i) fixedobj_pages[i].attr.parts.obj_size
128 #define set_page_full(i) fixedobj_pages[i].free_index = IMMOBILE_CARD_BYTES
129 #define page_full_p(i) (fixedobj_pages[i].free_index >= (int)IMMOBILE_CARD_BYTES)
130 #define fixedobj_page_wp(i) (fixedobj_pages[i].attr.parts.flags & WRITE_PROTECT)
132 /// Variable-length pages:
134 // Array of inverted write-protect flags, 1 bit per page.
135 unsigned int* varyobj_page_touched_bits;
136 static int n_bitmap_elts; // length of array measured in 'int's
138 // Array of offsets backwards in double-lispwords from the page end
139 // to the lowest-addressed object touching the page. This offset can
140 // point to a hole, but we prefer that it not. If the offset is zero,
141 // the page has no object other than possibly a hole resulting
142 // from a freed object.
143 unsigned short* varyobj_page_scan_start_offset;
145 // Array of page generation masks
146 unsigned char* varyobj_page_header_gens;
147 // Holes to be stuffed back into the managed free list.
148 lispobj varyobj_holes;
150 #define VARYOBJ_PAGE_GENS(x) varyobj_page_header_gens[x-FIRST_VARYOBJ_PAGE]
151 #define varyobj_page_touched(x) \
152 ((varyobj_page_touched_bits[(x-FIRST_VARYOBJ_PAGE)/32] >> (x&31)) & 1)
154 #ifdef VERIFY_PAGE_GENS
155 void check_fixedobj_page(low_page_index_t);
156 void check_varyobj_pages();
157 #endif
159 // Object header: generation byte --| |-- widetag
160 // v v
161 // 0xzzzzzzzz GGzzzzww
162 // arbitrary data -------- ---- length in words
164 // There is a hard constraint on NUM_GENERATIONS, which is currently 8.
165 // (0..5=normal, 6=pseudostatic, 7=scratch)
166 // It could be as high as 16 for 32-bit words (wherein scratch=gen15)
167 // or 32 for 64-bits words (wherein scratch=gen31).
168 // In each case, the VISITED flag bit weight would need to be modified.
169 // Shifting a 1 bit left by the contents of the generation byte
170 // must not overflow a register.
172 #ifdef LISP_FEATURE_LITTLE_ENDIAN
173 static inline void assign_generation(lispobj* obj, generation_index_t gen)
175 ((generation_index_t*)obj)[3] = gen;
177 // Turn a grey node black.
178 static inline void set_visited(lispobj* obj)
180 gc_dcheck(__immobile_obj_gen_bits(obj) == new_space);
181 ((generation_index_t*)obj)[3] |= IMMOBILE_OBJ_VISITED_FLAG;
183 #else
184 #error "Need to define assign_generation() for big-endian"
185 #endif
187 static inline void *
188 low_page_address(low_page_index_t page_num)
190 return ((char*)IMMOBILE_SPACE_START + (page_num * IMMOBILE_CARD_BYTES));
193 //// Variable-length utilities
195 /* Calculate the address where the first object touching this page starts. */
196 static inline lispobj*
197 varyobj_scan_start(low_page_index_t page_index)
199 return (lispobj*)((char*)low_page_address(page_index+1)
200 - varyobj_page_scan_start_offset[page_index - FIRST_VARYOBJ_PAGE]
201 * (2 * N_WORD_BYTES));
204 /* Return the generation mask for objects headers on 'page_index'
205 including at most one object that starts before the page but ends on
206 or after it.
207 If the scan start is within the page, i.e. less than DOUBLEWORDS_PER_PAGE
208 (note that the scan start is measured relative to the page end) then
209 we don't need to OR in the generation byte from an extra object,
210 as all headers on the page are accounted for in the page generation mask.
211 Also an empty page (where scan start is zero) avoids looking
212 at the next page's first object by accident via the same test. */
213 unsigned char varyobj_page_gens_augmented(low_page_index_t page_index)
215 return (varyobj_page_scan_start_offset[page_index - FIRST_VARYOBJ_PAGE] <= DOUBLEWORDS_PER_PAGE
216 ? 0 : (1<<__immobile_obj_generation(varyobj_scan_start(page_index))))
217 | VARYOBJ_PAGE_GENS(page_index);
220 //// Fixed-length object allocator
222 /* Return the index of an immobile page that is probably not totally full,
223 starting with 'hint_page' and wrapping around.
224 'attributes' determine an eligible page.
225 *IMMOBILE-SPACE-FREE-POINTER* is updated to point beyond the found page
226 if it previously did not. */
228 static int get_freeish_page(int hint_page, int attributes)
230 int page = hint_page;
231 lispobj *new_free_pointer, *old_free_pointer, *actual_old;
232 int page_attr_packed;
233 unsigned char best_genmask = 0xff;
234 int best_page = -1;
236 // Speed of this could be improved by keeping a linked list of pages
237 // with any space available, headed by a field in the page struct.
238 // This is totally lock-free / wait-free though, so it's really not
239 // too shabby, because it never has to deal with a page-table mutex.
240 do {
241 page_attr_packed = fixedobj_pages[page].attr.packed;
242 if (page_attr_packed == 0)
243 if ((page_attr_packed =
244 __sync_val_compare_and_swap(&fixedobj_pages[page].attr.packed,
245 0, attributes)) == 0) {
246 // Atomically assign MAX(old_free_pointer, new_free_pointer)
247 // into the free pointer.
248 new_free_pointer = low_page_address(page+1);
249 old_free_pointer = immobile_fixedobj_free_pointer;
250 while (new_free_pointer > old_free_pointer) {
251 actual_old =
252 __sync_val_compare_and_swap(&immobile_fixedobj_free_pointer,
253 old_free_pointer,
254 new_free_pointer);
255 if (actual_old == old_free_pointer)
256 break;
257 old_free_pointer = actual_old;
259 return page;
261 if (ATTRIBUTES_MATCH_P(page_attr_packed, attributes)
262 && !page_full_p(page)) {
263 // Try to avoid new objects on pages with any pseudo-static objects,
264 // because then touching the young object forces scanning the page,
265 // which is unfortunate if most things on it were untouched.
266 if (fixedobj_pages[page].gens < (1<<PSEUDO_STATIC_GENERATION)) {
267 // instant win
268 return page;
269 } else if (fixedobj_pages[page].gens < best_genmask) {
270 best_genmask = fixedobj_pages[page].gens;
271 best_page = page;
274 if (++page >= FIRST_VARYOBJ_PAGE) page = 0;
275 } while (page != hint_page);
276 if (best_page >= 0)
277 return best_page;
278 lose("No more immobile pages available");
281 // Unused, but possibly will be for some kind of collision-avoidance scheme
282 // on claiming of new free pages.
283 long immobile_alloc_collisions;
285 /* Beginning at page index *hint, attempt to find space
286 for an object on a page with page_attributes. Write its header word
287 and return a C (native) pointer. The start page MUST have the proper
288 characteristisc, but might be totally full.
290 Precondition: Lisp has established a pseudo-atomic section. */
292 /* There is a slightly different algorithm that would probably be faster
293 than what is currently implemented:
294 - hint should be the address of a word that you try to claim
295 as an object header; it moves from high-to-low instead of low-to-high.
296 It's easier to compute the page base than the last valid object start
297 if there are some wasted words at the end due to page size not being
298 a perfect multiple of object size.
299 - you do a CAS into that word, and either suceed or fail
300 - if you succeed, subtract the object spacing and compare
301 to the page's base address, which can be computed by
302 masking. if the next address is above or equal to the page start,
303 store it in the hint, otherwise mark the page full */
305 lispobj alloc_immobile_obj(int page_attributes, lispobj header, int* hint)
307 int page;
308 lispobj word;
309 char * page_data, * obj_ptr, * next_obj_ptr, * limit, * next_free;
310 int spacing_in_bytes = OBJ_SPACING(page_attributes) << WORD_SHIFT;
312 page = *hint;
313 gc_dcheck(low_page_address(page) < immobile_fixedobj_free_pointer);
314 do {
315 page_data = low_page_address(page);
316 obj_ptr = page_data + fixedobj_pages[page].free_index;
317 limit = page_data + IMMOBILE_CARD_BYTES - spacing_in_bytes;
318 while (obj_ptr <= limit) {
319 word = *(lispobj*)obj_ptr;
320 next_obj_ptr = obj_ptr + spacing_in_bytes;
321 if (fixnump(word) // a fixnum marks free space
322 && __sync_bool_compare_and_swap((lispobj*)obj_ptr,
323 word, header)) {
324 // The value formerly in the header word was the offset to
325 // the next hole. Use it to update the freelist pointer.
326 // Just slam it in.
327 fixedobj_pages[page].free_index = next_obj_ptr + word - page_data;
328 return (lispobj)obj_ptr;
330 // If some other thread updated the free_index
331 // to a larger value, use that. (See example below)
332 next_free = page_data + fixedobj_pages[page].free_index;
333 obj_ptr = next_free > next_obj_ptr ? next_free : next_obj_ptr;
335 set_page_full(page);
336 page = get_freeish_page(page+1 >= FIRST_VARYOBJ_PAGE ? 0 : page+1,
337 page_attributes);
338 *hint = page;
339 } while (1);
343 Example: Conside the freelist initially pointing to word index 6
344 Threads A, and B, and C each want to claim index 6.
345 - Thread A wins and then is switched out immediately after the CAS.
346 - Thread B fails to claim cell 6, claims cell 12 instead.
347 - Thread C fails to claim a cell and is switched out immediately
348 after the CAS.
349 - Thread B writes the index of the next hole, cell 18 into the
350 page's freelist cell.
351 - Thread A wakes up and writes 12 into the freelist cell.
352 - Thread C wakes up sees 12 for next_offset. 12 is greater than 6,
353 so it sets its next probe location to 12.
354 It fails the fixnump(header) test.
355 - Thread C sees that next_offset is still 12,
356 so it skips by the page's object spacing instead, and will continue
357 to do so until hitting the end of the page.
360 //// The collector
362 void update_immobile_nursery_bits()
364 low_page_index_t page;
365 lispobj fixedobj_free_ptr = (lispobj)immobile_fixedobj_free_pointer;
366 lispobj varyobj_free_ptr = (lispobj)immobile_space_free_pointer;
368 // Find the high water marks for this GC scavenge phase
369 // [avoid passing exactly IMMOBILE_SPACE_END, which has no page index]
370 max_used_fixedobj_page = find_immobile_page_index((void*)(fixedobj_free_ptr-1));
371 max_used_varyobj_page = find_immobile_page_index((void*)(varyobj_free_ptr-1));
373 immobile_scav_queue = (unsigned int*)low_page_address(max_used_varyobj_page+1);
374 gc_assert((IMMOBILE_SPACE_END - (uword_t)immobile_scav_queue) / sizeof(int)
375 >= QCAPACITY);
377 if (ENABLE_PAGE_PROTECTION) {
378 // Unprotect the in-use ranges. Any page could be written during scavenge
379 os_protect((os_vm_address_t)IMMOBILE_SPACE_START,
380 fixedobj_free_ptr - IMMOBILE_SPACE_START,
381 OS_VM_PROT_ALL);
383 // varyobj_free_ptr is typically not page-aligned - only by random chance
384 // might it be. Additionally we need a page beyond that for the re-scan queue.
385 os_vm_address_t limit = (char*)immobile_scav_queue + IMMOBILE_CARD_BYTES;
386 os_protect((os_vm_address_t)(IMMOBILE_VARYOBJ_SUBSPACE_START),
387 limit - (os_vm_address_t)IMMOBILE_VARYOBJ_SUBSPACE_START,
388 OS_VM_PROT_ALL);
391 for (page=0; page <= max_used_fixedobj_page ; ++page) {
392 // any page whose free index changed contains nursery objects
393 if (fixedobj_pages[page].free_index >> WORD_SHIFT !=
394 fixedobj_pages[page].prior_gc_free_word_index)
395 fixedobj_pages[page].gens |= 1;
396 #ifdef VERIFY_PAGE_GENS
397 check_fixedobj_page(page);
398 #endif
400 #ifdef VERIFY_PAGE_GENS
401 check_varyobj_pages();
402 #endif
405 /* Turn a white object grey. Also enqueue the object for re-scan if required */
406 void
407 enliven_immobile_obj(lispobj *ptr, int rescan) // a native pointer
409 if (widetag_of(*ptr) == SIMPLE_FUN_WIDETAG)
410 ptr = fun_code_header(ptr);
411 gc_assert(__immobile_obj_gen_bits(ptr) == from_space);
412 int pointerish = !unboxed_obj_widetag_p(widetag_of(*ptr));
413 assign_generation(ptr, (pointerish ? 0 : IMMOBILE_OBJ_VISITED_FLAG) | new_space);
414 low_page_index_t page_index = find_immobile_page_index(ptr);
416 if (page_index >= FIRST_VARYOBJ_PAGE) {
417 VARYOBJ_PAGE_GENS(page_index) |= 1<<new_space;
418 } else {
419 fixedobj_pages[page_index].gens |= 1<<new_space;
421 // If called from preserve_pointer(), then we haven't scanned immobile
422 // roots yet, so we only need ensure that this object's page's WP bit
423 // is cleared so that the page is not skipped during root scan.
424 if (!rescan) {
425 if (pointerish) {
426 if (page_index >= FIRST_VARYOBJ_PAGE)
427 varyobj_page_touched_bits[(page_index-FIRST_VARYOBJ_PAGE)/32]
428 |= 1 << (page_index & 31);
429 else
430 SET_WP_FLAG(page_index, WRITE_PROTECT_CLEARED);
432 return; // No need to enqueue.
435 // Do nothing if either we don't need to look for pointers in this object,
436 // or the work queue has already overflowed, causing a full scan.
437 if (!pointerish || immobile_scav_queue_count > QCAPACITY) return;
439 // count is either less than or equal to QCAPACITY.
440 // If equal, just bump the count to signify overflow.
441 if (immobile_scav_queue_count < QCAPACITY) {
442 immobile_scav_queue[immobile_scav_queue_head] =
443 (uword_t)ptr & 0xFFFFFFFF; // Drop the high bits
444 immobile_scav_queue_head = (immobile_scav_queue_head + 1) & (QCAPACITY - 1);
446 ++immobile_scav_queue_count;
449 /* If 'addr' points to an immobile object, then make the object
450 live by promotion. But if the object is not in the generation
451 being collected, do nothing */
452 void immobile_space_preserve_pointer(void* addr)
454 low_page_index_t page_index = find_immobile_page_index(addr);
455 if (page_index < 0)
456 return;
458 lispobj* object_start;
459 int valid = 0;
461 if (page_index >= FIRST_VARYOBJ_PAGE) {
462 // Restrict addr to lie below IMMOBILE_SPACE_FREE_POINTER.
463 // This way, if the gens byte is nonzero but there is
464 // a final array acting as filler on the remainder of the
465 // final page, we won't accidentally find that.
466 lispobj* scan_start;
467 valid = addr < (void*)immobile_space_free_pointer
468 && (varyobj_page_gens_augmented(page_index) & (1<<from_space)) != 0
469 && (scan_start = varyobj_scan_start(page_index)) <= (lispobj*)addr
470 && (object_start = gc_search_space(scan_start, addr)) != 0
471 /* gc_search_space can return filler objects, unlike
472 * search_immobile_space which can not */
473 && !immobile_filler_p(object_start)
474 && (instruction_ptr_p(addr, object_start)
475 || properly_tagged_descriptor_p(addr, object_start));
476 } else if (fixedobj_pages[page_index].gens & (1<<from_space)) {
477 int obj_spacing = (page_obj_align(page_index) << WORD_SHIFT);
478 int obj_index = ((uword_t)addr & (IMMOBILE_CARD_BYTES-1)) / obj_spacing;
479 dprintf((logfile,"Pointer %p is to immobile page %d, object %d\n",
480 addr, page_index, obj_index));
481 char* page_start_addr = (char*)((uword_t)addr & ~(IMMOBILE_CARD_BYTES-1));
482 object_start = (lispobj*)(page_start_addr + obj_index * obj_spacing);
483 valid = !fixnump(*object_start)
484 && (lispobj*)addr < object_start + page_obj_size(page_index)
485 && properly_tagged_descriptor_p(addr, object_start);
487 if (valid && __immobile_obj_gen_bits(object_start) == from_space) {
488 dprintf((logfile,"immobile obj @ %p (<- %p) is conservatively live\n",
489 header_addr, addr));
490 enliven_immobile_obj(object_start, 0);
494 // Loop over the newly-live objects, scavenging them for pointers.
495 // As with the ordinary gencgc algorithm, this uses almost no stack.
496 static void full_scavenge_immobile_newspace()
498 page_index_t page;
499 unsigned char bit = 1<<new_space;
501 // Fixed-size object pages.
503 for (page = 0; page <= max_used_fixedobj_page; ++page) {
504 if (!(fixedobj_pages[page].gens & bit)) continue;
505 // Skip amount within the loop is in bytes.
506 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
507 lispobj* obj = low_page_address(page);
508 // Use an inclusive, not exclusive, limit. On pages with dense packing
509 // (i.e. non-LAYOUT), if the object size does not evenly divide the page
510 // size, it is wrong to examine memory at an address which could be
511 // an object start, but for the fact that it runs off the page boundary.
512 // On the other hand, unused words hold 0, so it's kind of ok to read them.
513 lispobj* limit = (lispobj*)((char*)obj +
514 IMMOBILE_CARD_BYTES - obj_spacing);
515 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
516 if (!fixnump(*obj) && __immobile_obj_gen_bits(obj) == new_space) {
517 set_visited(obj);
518 lispobj header = *obj;
519 scavtab[widetag_of(header)](obj, header);
524 // Variable-size object pages
526 page = FIRST_VARYOBJ_PAGE - 1; // Subtract 1 because of pre-increment
527 while (1) {
528 // Find the next page with anything in newspace.
529 do {
530 if (++page > max_used_varyobj_page) return;
531 } while ((VARYOBJ_PAGE_GENS(page) & bit) == 0);
532 lispobj* obj = varyobj_scan_start(page);
533 do {
534 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
535 int n_words;
536 for ( ; obj < limit ; obj += n_words ) {
537 lispobj header = *obj;
538 if (__immobile_obj_gen_bits(obj) == new_space) {
539 set_visited(obj);
540 n_words = scavtab[widetag_of(header)](obj, header);
541 } else {
542 n_words = sizetab[widetag_of(header)](obj);
545 page = find_immobile_page_index(obj);
546 // Bail out if exact absolute end of immobile space was reached.
547 if (page < 0) return;
548 // If 'page' should be scanned, then pick up where we left off,
549 // without recomputing 'obj' but setting a higher 'limit'.
550 } while (VARYOBJ_PAGE_GENS(page) & bit);
554 /// Repeatedly scavenge immobile newspace work queue until we find no more
555 /// reachable objects within. (They might be in dynamic space though).
556 /// If queue overflow already happened, then a worst-case full scan is needed.
557 /// If it didn't, we try to drain the queue, hoping that overflow does
558 /// not happen while doing so.
559 /// The approach taken is more subtle than just dequeuing each item,
560 /// scavenging, and letting the outer 'while' loop take over.
561 /// That would be ok, but could cause more full scans than necessary.
562 /// Instead, since each entry in the queue is useful information
563 /// in the non-overflow condition, perform all the work indicated thereby,
564 /// rather than considering the queue discardable as soon as overflow happens.
565 /// Essentially we just have to capture the valid span of enqueued items,
566 /// because the queue state is inconsistent when 'count' exceeds 'capacity'.
567 void scavenge_immobile_newspace()
569 while (immobile_scav_queue_count) {
570 if (immobile_scav_queue_count > QCAPACITY) {
571 immobile_scav_queue_count = 0;
572 full_scavenge_immobile_newspace();
573 } else {
574 int queue_index_from = (immobile_scav_queue_head - immobile_scav_queue_count)
575 & (QCAPACITY - 1);
576 int queue_index_to = immobile_scav_queue_head;
577 int i = queue_index_from;
578 // The termination condition can't be expressed as an inequality,
579 // since the indices might be reversed due to wraparound.
580 // To express as equality entails forcing at least one iteration
581 // since the ending index might be the starting index.
582 do {
583 lispobj* obj = (lispobj*)(uword_t)immobile_scav_queue[i];
584 i = (1 + i) & (QCAPACITY-1);
585 // Only decrement the count if overflow did not happen.
586 // The first iteration of this loop will decrement for sure,
587 // but subsequent iterations might not.
588 if (immobile_scav_queue_count <= QCAPACITY)
589 --immobile_scav_queue_count;
590 if (!(__immobile_obj_gen_bits(obj) & IMMOBILE_OBJ_VISITED_FLAG)) {
591 set_visited(obj);
592 lispobj header = *obj;
593 scavtab[widetag_of(header)](obj, header);
595 } while (i != queue_index_to);
600 // Return a page >= page_index having potential old->young pointers,
601 // or -1 if there isn't one.
602 static int next_varyobj_root_page(unsigned int page_index,
603 unsigned int end_bitmap_index,
604 unsigned char genmask)
606 unsigned int map_index = (page_index - FIRST_VARYOBJ_PAGE) / 32;
607 if (map_index >= end_bitmap_index) return -1;
608 int bit_index = page_index & 31;
609 // Look only at bits of equal or greater weight than bit_index.
610 unsigned int word = (0xFFFFFFFFU << bit_index) & varyobj_page_touched_bits[map_index];
611 while (1) {
612 if (word) {
613 bit_index = ffs(word) - 1;
614 page_index = FIRST_VARYOBJ_PAGE + map_index * 32 + bit_index;
615 if (varyobj_page_gens_augmented(page_index) & genmask)
616 return page_index;
617 else {
618 word ^= (1<<bit_index);
619 continue;
622 if (++map_index >= end_bitmap_index) return -1;
623 word = varyobj_page_touched_bits[map_index];
627 void
628 scavenge_immobile_roots(generation_index_t min_gen, generation_index_t max_gen)
630 // example: scavenging gens 2..6, the mask of root gens is #b1111100
631 int genmask = ((1 << (max_gen - min_gen + 1)) - 1) << min_gen;
633 low_page_index_t page;
634 for (page = 0; page <= max_used_fixedobj_page ; ++page) {
635 if (fixedobj_page_wp(page) || !(fixedobj_pages[page].gens & genmask))
636 continue;
637 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
638 lispobj* obj = low_page_address(page);
639 lispobj* limit = (lispobj*)((char*)obj +
640 IMMOBILE_CARD_BYTES - obj_spacing);
641 int gen;
642 // Immobile space can only contain objects with a header word,
643 // no conses, so any fixnum where a header could be is not a live
644 // object.
645 do {
646 if (!fixnump(*obj) && (genmask >> (gen=__immobile_obj_gen_bits(obj)) & 1)) {
647 if (gen == new_space) { set_visited(obj); }
648 lispobj header = *obj;
649 scavtab[widetag_of(header)](obj, header);
651 } while ((obj = (lispobj*)((char*)obj + obj_spacing)) <= limit);
654 // Variable-length object pages
655 unsigned n_varyobj_pages = 1+max_used_varyobj_page-FIRST_VARYOBJ_PAGE;
656 unsigned end_bitmap_index = (n_varyobj_pages+31)/32;
657 page = next_varyobj_root_page(FIRST_VARYOBJ_PAGE, end_bitmap_index, genmask);
658 while (page >= 0) {
659 lispobj* obj = varyobj_scan_start(page);
660 do {
661 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
662 int n_words, gen;
663 for ( ; obj < limit ; obj += n_words ) {
664 lispobj header = *obj;
665 if (genmask >> (gen=__immobile_obj_gen_bits(obj)) & 1) {
666 if (gen == new_space) { set_visited(obj); }
667 n_words = scavtab[widetag_of(header)](obj, header);
668 } else {
669 n_words = sizetab[widetag_of(header)](obj);
672 page = find_immobile_page_index(obj);
673 } while (page > 0
674 && (VARYOBJ_PAGE_GENS(page) & genmask)
675 && varyobj_page_touched(page));
676 page = next_varyobj_root_page(1+page, end_bitmap_index, genmask);
678 scavenge_immobile_newspace();
681 #include "genesis/layout.h"
682 #define LAYOUT_SIZE (sizeof (struct layout)/N_WORD_BYTES)
683 #define LAYOUT_ALIGN 256 /*bytes*/
684 #define LAYOUT_OF_LAYOUT ((IMMOBILE_SPACE_START+2*LAYOUT_ALIGN)|INSTANCE_POINTER_LOWTAG)
685 #define LAYOUT_OF_PACKAGE ((IMMOBILE_SPACE_START+8*LAYOUT_ALIGN)|INSTANCE_POINTER_LOWTAG)
687 // As long as Lisp doesn't have any native allocators (vops and whatnot)
688 // it doesn't need to access these values.
689 int layout_page_hint, symbol_page_hint, fdefn_page_hint;
691 // For the three different page characteristics that we need,
692 // claim a page that works for those characteristics.
693 void set_immobile_space_hints()
695 // The allocator doesn't check whether each 'hint' points to an
696 // expected kind of page, so we have to ensure up front that
697 // allocations start on different pages. i.e. You can point to
698 // a totally full page, but you can't point to a wrong page.
699 // It doesn't work to just assign these to consecutive integers
700 // without also updating the page attributes.
702 // Object sizes must be multiples of 2 because the n_words value we pass
703 // to scavenge() is gotten from the page attributes, and scavenge asserts
704 // that the ending address is aligned to a doubleword boundary as expected.
706 // LAYOUTs are 256-byte-aligned so that the low byte contains no information.
707 // This makes it possible to recover a layout pointer from an instance header
708 // by simply changing the low byte to instance-pointer-lowtag.
709 // As a test of objects using larger-than-required alignment,
710 // the 64-bit implementation uses 256-byte alignment for layouts,
711 // even though the header can store all bits of the layout pointer.
712 // The 32-bit implementation would also need somewhere different to store
713 // the generation byte of each layout, which is a minor annoyance.
714 layout_page_hint = get_freeish_page(0, MAKE_ATTR(LAYOUT_ALIGN / N_WORD_BYTES, // spacing
715 CEILING(LAYOUT_SIZE,2),
716 0));
717 symbol_page_hint = get_freeish_page(0, MAKE_ATTR(CEILING(SYMBOL_SIZE,2),
718 CEILING(SYMBOL_SIZE,2),
719 0));
720 fdefn_page_hint = get_freeish_page(0, MAKE_ATTR(CEILING(FDEFN_SIZE,2),
721 CEILING(FDEFN_SIZE,2),
722 0));
725 void write_protect_immobile_space()
727 immobile_scav_queue = NULL;
728 immobile_scav_queue_head = 0;
730 set_immobile_space_hints();
732 if (!ENABLE_PAGE_PROTECTION)
733 return;
735 // Now find contiguous ranges of pages that are protectable,
736 // minimizing the number of system calls as much as possible.
737 int i, start = -1, end = -1; // inclusive bounds on page indices
738 for (i = max_used_fixedobj_page ; i >= 0 ; --i) {
739 if (fixedobj_page_wp(i)) {
740 if (end < 0) end = i;
741 start = i;
743 if (end >= 0 && (!fixedobj_page_wp(i) || i == 0)) {
744 os_protect(low_page_address(start),
745 IMMOBILE_CARD_BYTES * (1 + end - start),
746 OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
747 start = end = -1;
750 #define varyobj_page_wp(x) !varyobj_page_touched(x)
751 for (i = max_used_varyobj_page ; i >= FIRST_VARYOBJ_PAGE ; --i) {
752 if (varyobj_page_wp(i)) {
753 if (end < 0) end = i;
754 start = i;
756 if (end >= 0 && (!varyobj_page_wp(i) || i == FIRST_VARYOBJ_PAGE)) {
757 os_protect(low_page_address(start),
758 IMMOBILE_CARD_BYTES * (1 + end - start),
759 OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
760 start = end = -1;
763 #undef varyobj_page_wp
766 // Scan range between start and end (exclusive) for old-to-young pointers.
767 // 'keep_gen' is the value of the generation byte of objects that were
768 // candidates to become garbage, but remain live after this gc.
769 // It will necessarily have the VISITED flag on.
770 // 'new_gen' is the generation number that those objects will have
771 // after collection, which is either the same generation or one higher,
772 // depending on the 'raise' flag for this GC cycle.
773 static int
774 range_points_to_younger_p(lispobj* obj, lispobj* end,
775 int gen, int keep_gen, int new_gen)
777 #ifdef DEBUG
778 lispobj* __attribute__((unused)) saved_obj = obj, __attribute__((unused)) header = *obj;
779 #endif
780 do {
781 lispobj thing = *obj;
782 if (is_lisp_pointer(thing)) {
783 int to_page = find_page_index((void*)thing),
784 to_gen = 255;
785 if (to_page >= 0) { // points to ordinary dynamic space
786 to_gen = page_table[to_page].gen;
787 if (to_gen == PSEUDO_STATIC_GENERATION+1) // scratch gen
788 to_gen = new_gen; // is actually this
789 } else if (immobile_space_p(thing)) {
790 // Processing the code-entry-points slot of a code component
791 // requires the general variant of immobile_obj_gen_bits
792 // because the pointed-to object is a simple-fun.
793 to_gen = immobile_obj_gen_bits(native_pointer(thing));
794 if (to_gen == keep_gen) // keep gen
795 to_gen = new_gen; // is actually this
797 if (to_gen < gen) {
798 return 1; // yes, points to younger
801 } while (++obj < end);
802 return 0; // no, does not point to younger
805 // Scan a fixed-size object for old-to-young pointers.
806 // Since fixed-size objects are boxed and on known boundaries,
807 // we never start in the middle of random bytes, so the answer is exact.
808 static inline boolean
809 fixedobj_points_to_younger_p(lispobj* obj, int n_words,
810 int gen, int keep_gen, int new_gen)
812 unsigned char widetag = widetag_of(*obj);
813 lispobj __attribute__((unused)) funobj[1], layout[1];
814 lispobj lbitmap;
816 switch (widetag) {
817 #ifdef LISP_FEATURE_IMMOBILE_CODE
818 case FDEFN_WIDETAG:
819 // the seemingly silly use of an array is because points_to_younger_p()
820 // expects to get address ranges, not individual objects
821 funobj[0] = fdefn_raw_referent((struct fdefn*)obj);
822 return range_points_to_younger_p(funobj, funobj+1, gen, keep_gen, new_gen)
823 || range_points_to_younger_p(obj+1, obj+3, gen, keep_gen, new_gen);
824 #endif
825 case INSTANCE_WIDETAG:
826 case FUNCALLABLE_INSTANCE_WIDETAG:
827 layout[0] = instance_layout(obj); // same as above
828 if (range_points_to_younger_p(layout, layout+1, gen, keep_gen, new_gen))
829 return 1;
830 lbitmap = LAYOUT(layout[0])->bitmap;
831 if (lbitmap != make_fixnum(-1)) {
832 gc_assert(fixnump(lbitmap)); // No bignums (yet)
833 sword_t bitmap = (sword_t)lbitmap >> N_FIXNUM_TAG_BITS;
834 lispobj* where = obj + 1;
835 for ( ; --n_words ; ++where, bitmap >>= 1 )
836 if ((bitmap & 1) != 0 &&
837 range_points_to_younger_p(where, where+1, gen, keep_gen, new_gen))
838 return 1;
839 return 0;
841 // FALLTHROUGH_INTENDED
843 return range_points_to_younger_p(obj+1, obj+n_words, gen, keep_gen, new_gen);
846 static boolean
847 varyobj_points_to_younger_p(lispobj* obj, int gen, int keep_gen, int new_gen,
848 os_vm_address_t page_begin,
849 os_vm_address_t page_end) // upper (exclusive) bound
851 lispobj *begin, *end, word = *obj;
852 unsigned char widetag = widetag_of(word);
853 if (widetag == CODE_HEADER_WIDETAG) { // usual case. Like scav_code_header()
854 for_each_simple_fun(i, function_ptr, (struct code*)obj, 0, {
855 begin = SIMPLE_FUN_SCAV_START(function_ptr);
856 end = begin + SIMPLE_FUN_SCAV_NWORDS(function_ptr);
857 if (page_begin > (os_vm_address_t)begin) begin = (lispobj*)page_begin;
858 if (page_end < (os_vm_address_t)end) end = (lispobj*)page_end;
859 if (end > begin
860 && range_points_to_younger_p(begin, end, gen, keep_gen, new_gen))
861 return 1;
863 begin = obj + 1; // skip the header
864 end = obj + code_header_words(word); // exclusive bound on boxed slots
865 } else if (widetag == SIMPLE_VECTOR_WIDETAG) {
866 sword_t length = fixnum_value(((struct vector *)obj)->length);
867 begin = obj + 2; // skip the header and length
868 end = obj + CEILING(length + 2, 2);
869 } else if (unboxed_obj_widetag_p(widetag)) {
870 return 0;
871 } else {
872 lose("Unexpected widetag @ %p", obj);
874 // Fallthrough: scan words from begin to end
875 if (page_begin > (os_vm_address_t)begin) begin = (lispobj*)page_begin;
876 if (page_end < (os_vm_address_t)end) end = (lispobj*)page_end;
877 if (end > begin && range_points_to_younger_p(begin, end, gen, keep_gen, new_gen))
878 return 1;
879 return 0;
882 /// The next two functions are analogous to 'update_page_write_prot()'
883 /// but they differ in that they are "precise" - random code bytes that look
884 /// like pointers are not accidentally treated as pointers.
886 // If 'page' does not contain any objects that points to an object
887 // younger than themselves, then return true.
888 // This is called on pages that do not themselves contain objects of
889 // the generation being collected, but might contain pointers
890 // to younger generations, which we detect by a cleared WP status bit.
891 // The bit is cleared on any write, though, even of a non-pointer,
892 // so this unfortunately has to be tested much more often than we'd like.
893 static inline boolean can_wp_fixedobj_page(page_index_t page, int keep_gen, int new_gen)
895 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
896 int obj_size_words = page_obj_size(page);
897 lispobj* obj = low_page_address(page);
898 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES - obj_spacing);
899 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) )
900 if (!fixnump(*obj) && // an object header
901 fixedobj_points_to_younger_p(obj, obj_size_words,
902 __immobile_obj_generation(obj),
903 keep_gen, new_gen))
904 return 0;
905 return 1;
908 // To scan _only_ 'page' is impossible in general, but we can act like only
909 // one page was scanned by backing up to the first object whose end is on
910 // or after it, and then restricting points_to_younger within the boundaries.
911 // Doing it this way is probably much better than conservatively assuming
912 // that any word satisfying is_lisp_pointer() is a pointer.
913 static inline boolean can_wp_varyobj_page(page_index_t page, int keep_gen, int new_gen)
915 lispobj *begin = (lispobj*)low_page_address(page);
916 lispobj *end = begin + WORDS_PER_PAGE;
917 lispobj *obj = varyobj_scan_start(page);
918 for ( ; obj < end ; obj += sizetab[widetag_of(*obj)](obj) ) {
919 gc_assert(other_immediate_lowtag_p(*obj));
920 if (!immobile_filler_p(obj) &&
921 varyobj_points_to_younger_p(obj,
922 __immobile_obj_generation(obj),
923 keep_gen, new_gen,
924 (os_vm_address_t)begin,
925 (os_vm_address_t)end))
926 return 0;
928 return 1;
932 Sweep immobile space by zeroing the memory of trashed objects
933 and linking them into the freelist.
935 Possible improvements:
936 - If an entire page becomes nothing but holes, we could bzero it
937 instead of object-at-a-time clearing. But it's not known to be
938 so until after the sweep, so it would entail two passes per page,
939 one to mark holes and one to zero them.
940 - And perhaps bzero could be used on ranges of holes, because
941 in that case each hole's pointer to the next hole is zero as well.
944 #define SETUP_GENS() \
945 /* Only care about pages with something in old or new space. */ \
946 int relevant_genmask = (1 << from_space) | (1 << new_space); \
947 /* Objects whose gen byte is 'keep_gen' are alive. */ \
948 int keep_gen = IMMOBILE_OBJ_VISITED_FLAG | new_space; \
949 /* Objects whose gen byte is 'from_space' are trash. */ \
950 int discard_gen = from_space; \
951 /* Moving non-garbage into either 'from_space' or 'from_space+1' */ \
952 generation_index_t new_gen = from_space + (raise!=0)
954 // The new value of the page generation mask is computed as follows:
955 // If 'raise' = 1 then:
956 // Nothing resides in 'from_space', and 'from_space+1' gains new objects
957 // if and only if any objects on the page were retained.
958 // If 'raise' = 0 then:
959 // Nothing resides in the scratch generation, and 'from_space'
960 // has objects if and only if any objects were retained.
961 #define COMPUTE_NEW_MASK(var, old) \
962 int var = old & ~(1<<from_space); \
963 if ( raise ) \
964 var |= 1<<(from_space+1) & any_kept; \
965 else \
966 var = (var & ~(1<<new_space)) | (1<<from_space & any_kept)
968 static void
969 sweep_fixedobj_pages(int raise)
971 char *page_base;
972 lispobj *obj, *limit, *hole;
973 // This will be needed for space accounting.
974 // threads might fail to consume all the space on a page.
975 // By storing in the page table the count of holes that really existed
976 // at the start of the prior GC, and subtracting from that the number
977 // that exist now, we know how much usable space was obtained (per page).
978 int n_holes = 0;
979 int word_idx;
981 SETUP_GENS();
983 low_page_index_t page;
984 for (page = 0; page <= max_used_fixedobj_page; ++page) {
985 // On pages that won't need manipulation of the freelist,
986 // we try to do less work than for pages that need it.
987 if (!(fixedobj_pages[page].gens & relevant_genmask)) {
988 // Scan for old->young pointers, and WP if there are none.
989 if (ENABLE_PAGE_PROTECTION && !fixedobj_page_wp(page)
990 && fixedobj_pages[page].gens > 1
991 && can_wp_fixedobj_page(page, keep_gen, new_gen))
992 SET_WP_FLAG(page, WRITE_PROTECT);
993 continue;
995 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
996 int obj_size_words = page_obj_size(page);
997 page_base = low_page_address(page);
998 limit = (lispobj*)(page_base + IMMOBILE_CARD_BYTES - obj_spacing);
999 obj = (lispobj*)page_base;
1000 hole = NULL;
1001 int any_kept = 0; // was anything moved to the kept generation
1002 n_holes = 0;
1004 // wp_it is 1 if we should try to write-protect it now.
1005 // If already write-protected, skip the tests.
1006 int wp_it = ENABLE_PAGE_PROTECTION && !fixedobj_page_wp(page);
1007 int gen;
1008 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1009 if (fixnump(*obj)) { // was already a hole
1010 trash_it:
1011 // re-link it into the new freelist
1012 if (hole)
1013 // store the displacement from the end of the object
1014 // at prev_hole to the start of this object.
1015 *hole = (lispobj)((char*)obj - ((char*)hole + obj_spacing));
1016 else // this is the first seen hole on the page
1017 // record the byte offset to that hole
1018 fixedobj_pages[page].free_index = (char*)obj - page_base;
1019 hole = obj;
1020 n_holes ++;
1021 } else if ((gen = __immobile_obj_gen_bits(obj)) == discard_gen) { // trash
1022 for (word_idx=obj_size_words-1 ; word_idx > 0 ; --word_idx)
1023 obj[word_idx] = 0;
1024 goto trash_it;
1025 } else if (gen == keep_gen) {
1026 assign_generation(obj, gen = new_gen);
1027 #ifdef DEBUG
1028 gc_assert(!fixedobj_points_to_younger_p(obj, obj_size_words,
1029 gen, keep_gen, new_gen));
1030 #endif
1031 any_kept = -1;
1032 } else if (wp_it && fixedobj_points_to_younger_p(obj, obj_size_words,
1033 gen, keep_gen, new_gen))
1034 wp_it = 0;
1036 if ( hole ) // terminate the chain of holes
1037 *hole = (lispobj)((char*)obj - ((char*)hole + obj_spacing));
1038 fixedobj_pages[page].prior_gc_free_word_index =
1039 fixedobj_pages[page].free_index >> WORD_SHIFT;
1041 COMPUTE_NEW_MASK(mask, fixedobj_pages[page].gens);
1042 if ( mask ) {
1043 fixedobj_pages[page].gens = mask;
1044 if (wp_it) {
1045 SET_WP_FLAG(page, WRITE_PROTECT);
1046 dprintf((logfile, "Lowspace: set WP on page %d\n", page));
1048 } else {
1049 dprintf((logfile,"page %d is all garbage\n", page));
1050 fixedobj_pages[page].attr.packed = 0;
1052 #ifdef DEBUG
1053 check_fixedobj_page(page);
1054 #endif
1055 dprintf((logfile,"page %d: %d holes\n", page, n_holes));
1059 void verify_immobile_page_protection(int,int);
1061 // Scan for freshly trashed objects and turn them into filler.
1062 // Lisp is responsible for consuming the free space
1063 // when it next allocates a variable-size object.
1064 static void
1065 sweep_varyobj_pages(int raise)
1067 SETUP_GENS();
1069 lispobj* free_pointer = immobile_space_free_pointer;
1070 low_page_index_t page;
1071 for (page = FIRST_VARYOBJ_PAGE; page <= max_used_varyobj_page; ++page) {
1072 int genmask = VARYOBJ_PAGE_GENS(page);
1073 if (!(genmask & relevant_genmask)) { // Has nothing in oldspace or newspace.
1074 // Scan for old->young pointers, and WP if there are none.
1075 if (ENABLE_PAGE_PROTECTION && varyobj_page_touched(page)
1076 && varyobj_page_gens_augmented(page) > 1
1077 && can_wp_varyobj_page(page, keep_gen, new_gen))
1078 varyobj_page_touched_bits[(page - FIRST_VARYOBJ_PAGE)/32] &= ~(1<<(page & 31));
1079 continue;
1081 lispobj* page_base = (lispobj*)low_page_address(page);
1082 lispobj* limit = page_base + WORDS_PER_PAGE;
1083 if (limit > free_pointer) limit = free_pointer;
1084 int any_kept = 0; // was anything moved to the kept generation
1085 // wp_it is 1 if we should try to write-protect it now.
1086 // If already write-protected, skip the tests.
1087 int wp_it = ENABLE_PAGE_PROTECTION && varyobj_page_touched(page);
1088 lispobj* obj = varyobj_scan_start(page);
1089 int size, gen;
1091 if (obj < page_base) {
1092 // An object whose tail is on this page, or which spans this page,
1093 // would have been promoted/kept while dealing with the page with
1094 // the object header. Therefore we don't need to consider that object,
1095 // * except * that we do need to consider whether it is an old object
1096 // pointing to a young object.
1097 if (wp_it // If we wanted to try write-protecting this page,
1098 // and the object starting before this page is strictly older
1099 // than the generation that we're moving retained objects into
1100 && (gen = __immobile_obj_gen_bits(obj)) > new_gen
1101 // and it contains an old->young pointer
1102 && varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1103 (os_vm_address_t)page_base,
1104 (os_vm_address_t)limit)) {
1105 wp_it = 0;
1107 // We MUST skip this object in the sweep, because in the case of
1108 // non-promotion (raise=0), we could see an object in from_space
1109 // and believe it to be dead.
1110 obj += sizetab[widetag_of(*obj)](obj);
1111 // obj can't hop over this page. If it did, there would be no
1112 // headers on the page, and genmask would have been zero.
1113 gc_assert(obj < limit);
1115 for ( ; obj < limit ; obj += size ) {
1116 lispobj word = *obj;
1117 size = sizetab[widetag_of(word)](obj);
1118 if (immobile_filler_p(obj)) { // do nothing
1119 } else if ((gen = __immobile_obj_gen_bits(obj)) == discard_gen) {
1120 if (size < 4)
1121 lose("immobile object @ %p too small to free", obj);
1122 else { // Create a filler object.
1123 struct code* code = (struct code*)obj;
1124 code->header = 2<<N_WIDETAG_BITS | CODE_HEADER_WIDETAG;
1125 code->code_size = make_fixnum((size - 2) * N_WORD_BYTES);
1126 code->debug_info = varyobj_holes;
1127 varyobj_holes = (lispobj)code;
1129 } else if (gen == keep_gen) {
1130 assign_generation(obj, gen = new_gen);
1131 #ifdef DEBUG
1132 gc_assert(!varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1133 (os_vm_address_t)page_base,
1134 (os_vm_address_t)limit));
1135 #endif
1136 any_kept = -1;
1137 } else if (wp_it &&
1138 varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1139 (os_vm_address_t)page_base,
1140 (os_vm_address_t)limit))
1141 wp_it = 0;
1143 COMPUTE_NEW_MASK(mask, VARYOBJ_PAGE_GENS(page));
1144 VARYOBJ_PAGE_GENS(page) = mask;
1145 if ( mask && wp_it )
1146 varyobj_page_touched_bits[(page - FIRST_VARYOBJ_PAGE)/32] &= ~(1 << (page & 31));
1148 #ifdef DEBUG
1149 verify_immobile_page_protection(keep_gen, new_gen);
1150 #endif
1153 static void compute_immobile_space_bound()
1155 int max;
1156 // find the highest page in use
1157 for (max = FIRST_VARYOBJ_PAGE-1 ; max >= 0 ; --max)
1158 if (fixedobj_pages[max].attr.parts.obj_size)
1159 break;
1160 max_used_fixedobj_page = max; // this is a page index, not the number of pages.
1161 immobile_fixedobj_free_pointer =
1162 (lispobj*)(IMMOBILE_SPACE_START + IMMOBILE_CARD_BYTES*(1+max));
1164 for (max = (IMMOBILE_SPACE_SIZE/IMMOBILE_CARD_BYTES)-1 ;
1165 max >= FIRST_VARYOBJ_PAGE ; --max)
1166 if (varyobj_page_gens_augmented(max))
1167 break;
1168 max_used_varyobj_page = max; // this is a page index, not the number of pages.
1171 // TODO: (Maybe this won't work. Not sure yet.) rather than use the
1172 // same 'raise' concept as in gencgc, each immobile object can store bits
1173 // indicating whether it has survived any GC at its current generation.
1174 // If it has, then it gets promoted next time, rather than all or nothing
1175 // being promoted from the generation getting collected.
1176 void
1177 sweep_immobile_space(int raise)
1179 gc_assert(immobile_scav_queue_count == 0);
1180 sweep_fixedobj_pages(raise);
1181 sweep_varyobj_pages(raise);
1182 compute_immobile_space_bound();
1185 static void gc_init_immobile()
1187 #ifdef DEBUG
1188 logfile = stderr;
1189 #endif
1190 int n_fixedobj_pages = FIRST_VARYOBJ_PAGE;
1191 int n_varyobj_pages = (IMMOBILE_SPACE_SIZE - IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE)
1192 / IMMOBILE_CARD_BYTES;
1193 fixedobj_pages = calloc(n_fixedobj_pages, sizeof(struct fixedobj_page));
1194 gc_assert(fixedobj_pages);
1196 n_bitmap_elts = (n_varyobj_pages + 31) / 32;
1197 int request = n_bitmap_elts * sizeof (int)
1198 + n_varyobj_pages * (sizeof (short)+sizeof (char));
1199 char* varyobj_page_tables = calloc(1, request);
1200 gc_assert(varyobj_page_tables);
1201 varyobj_page_touched_bits = (unsigned int*)varyobj_page_tables;
1202 // The conservative value for 'touched' is 1.
1203 memset(varyobj_page_touched_bits, 0xff, n_bitmap_elts * sizeof (int));
1204 varyobj_page_scan_start_offset = (unsigned short*)(varyobj_page_touched_bits + n_bitmap_elts);
1205 varyobj_page_header_gens = (unsigned char*)(varyobj_page_scan_start_offset + n_varyobj_pages);
1208 /* Because the immobile page table is not dumped into a core image,
1209 we have to reverse-engineer the characteristics of each page,
1210 which means figuring out what the object spacing should be.
1211 This is not difficult, but is a bit of a kludge */
1213 static inline int immobile_obj_spacing(lispobj header_word, lispobj *obj,
1214 int actual_size)
1216 if (widetag_of(header_word) == INSTANCE_WIDETAG &&
1217 instance_layout(obj) == LAYOUT_OF_LAYOUT)
1218 return LAYOUT_ALIGN / N_WORD_BYTES;
1219 else
1220 return actual_size; // in words
1223 // Set the characteristics of each used page at image startup time.
1224 void immobile_space_coreparse(uword_t fixedobj_len, uword_t varyobj_len)
1226 int n_pages, word_idx, page;
1227 uword_t address;
1229 gc_init_immobile();
1231 address = IMMOBILE_SPACE_START;
1232 n_pages = (fixedobj_len + IMMOBILE_CARD_BYTES - 1) / IMMOBILE_CARD_BYTES;
1233 for (page = 0 ; page < n_pages ; ++page) {
1234 lispobj* page_data = low_page_address(page);
1235 for (word_idx = 0 ; word_idx < WORDS_PER_PAGE ; ++word_idx) {
1236 lispobj* obj = page_data + word_idx;
1237 lispobj header = *obj;
1238 if (!fixnump(header)) {
1239 gc_assert(other_immediate_lowtag_p(*obj));
1240 int size = sizetab[widetag_of(header)](obj);
1241 fixedobj_pages[page].attr.parts.obj_size = size;
1242 fixedobj_pages[page].attr.parts.obj_align
1243 = immobile_obj_spacing(header, obj, size);
1244 fixedobj_pages[page].gens |= 1 << __immobile_obj_gen_bits(obj);
1245 if (ENABLE_PAGE_PROTECTION)
1246 fixedobj_pages[page].attr.parts.flags = WRITE_PROTECT;
1247 break;
1251 address = IMMOBILE_VARYOBJ_SUBSPACE_START;
1252 n_pages = (varyobj_len + IMMOBILE_CARD_BYTES - 1) / IMMOBILE_CARD_BYTES;
1253 lispobj* obj = (lispobj*)address;
1254 lispobj* space_limit = (lispobj*)(address + varyobj_len);
1255 int n_words;
1256 low_page_index_t last_page = 0;
1257 // coreparse() already set immobile_space_free_pointer
1258 lispobj* limit = immobile_space_free_pointer;
1259 gc_assert(limit != 0 /* would be zero if not mmapped yet */
1260 && limit < space_limit);
1261 for ( ; obj < limit ; obj += n_words ) {
1262 gc_assert(other_immediate_lowtag_p(obj[0]));
1263 n_words = sizetab[widetag_of(*obj)](obj);
1264 if (immobile_filler_p(obj)) {
1265 // Holes were chained through the debug_info slot at save.
1266 // Just update the head of the chain.
1267 varyobj_holes = (lispobj)obj;
1268 continue;
1270 low_page_index_t first_page = find_immobile_page_index(obj);
1271 last_page = find_immobile_page_index(obj+n_words-1);
1272 // Only the page with this object header gets a bit in its gen mask.
1273 VARYOBJ_PAGE_GENS(first_page) |= 1<<__immobile_obj_gen_bits(obj);
1274 // For each page touched by this object, set the page's
1275 // scan_start_offset, unless it was already set.
1276 int page;
1277 for (page = first_page ; page <= last_page ; ++page) {
1278 if (!varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE]) {
1279 long offset = (char*)low_page_address(page+1) - (char*)obj;
1280 varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE]
1281 = offset >> (WORD_SHIFT + 1);
1285 // Write a padding object if necessary
1286 if ((uword_t)limit & (IMMOBILE_CARD_BYTES-1)) {
1287 int remainder = IMMOBILE_CARD_BYTES -
1288 ((uword_t)limit & (IMMOBILE_CARD_BYTES-1));
1289 limit[0] = SIMPLE_ARRAY_FIXNUM_WIDETAG;
1290 limit[1] = make_fixnum((remainder >> WORD_SHIFT) - 2);
1291 int size = sizetab[SIMPLE_ARRAY_FIXNUM_WIDETAG](limit);
1292 lispobj* padded_end = limit + size;
1293 gc_assert(!((uword_t)padded_end & (IMMOBILE_CARD_BYTES-1)));
1295 // Write-protect the pages occupied by the core file.
1296 // (There can be no inter-generation pointers.)
1297 if (ENABLE_PAGE_PROTECTION) {
1298 int page;
1299 for (page = FIRST_VARYOBJ_PAGE ; page <= last_page ; ++page)
1300 varyobj_page_touched_bits[(page-FIRST_VARYOBJ_PAGE)/32] &= ~(1<<(page & 31));
1302 compute_immobile_space_bound();
1303 struct code* code = (struct code*)address;
1304 while (!code_n_funs(code)) {
1305 gc_assert(widetag_of(code->header) == CODE_HEADER_WIDETAG);
1306 code = (struct code*)
1307 (lispobj*)code + sizetab[CODE_HEADER_WIDETAG]((lispobj*)code);
1309 ASM_ROUTINES_END = (unsigned)(uword_t)code;
1312 // Demote pseudo-static to highest normal generation
1313 // so that all objects become eligible for collection.
1314 void prepare_immobile_space_for_final_gc()
1316 int page;
1317 char* page_base;
1318 char* page_end = (char*)immobile_fixedobj_free_pointer;
1320 // The list of holes need not be saved.
1321 SYMBOL(IMMOBILE_FREELIST)->value = NIL;
1323 for (page_base = (char*)IMMOBILE_SPACE_START, page = 0 ;
1324 page_base < page_end ;
1325 page_base += IMMOBILE_CARD_BYTES, ++page) {
1326 unsigned char mask = fixedobj_pages[page].gens;
1327 if (mask & 1<<PSEUDO_STATIC_GENERATION) {
1328 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
1329 lispobj* obj = (lispobj*)page_base;
1330 lispobj* limit = (lispobj*)(page_base + IMMOBILE_CARD_BYTES - obj_spacing);
1331 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1332 if (!fixnump(*obj)
1333 && __immobile_obj_gen_bits(obj) == PSEUDO_STATIC_GENERATION)
1334 assign_generation(obj, HIGHEST_NORMAL_GENERATION);
1336 fixedobj_pages[page].gens = (mask & ~(1<<PSEUDO_STATIC_GENERATION))
1337 | 1<<HIGHEST_NORMAL_GENERATION;
1341 lispobj* obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1342 lispobj* limit = immobile_space_free_pointer;
1343 for ( ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
1344 if (__immobile_obj_gen_bits(obj) == PSEUDO_STATIC_GENERATION)
1345 assign_generation(obj, HIGHEST_NORMAL_GENERATION);
1347 int max_page = find_immobile_page_index(limit-1);
1348 for ( page = FIRST_VARYOBJ_PAGE ; page <= max_page ; ++page ) {
1349 int mask = VARYOBJ_PAGE_GENS(page);
1350 if (mask & (1<<PSEUDO_STATIC_GENERATION)) {
1351 VARYOBJ_PAGE_GENS(page) = (mask & ~(1<<PSEUDO_STATIC_GENERATION))
1352 | 1<<HIGHEST_NORMAL_GENERATION;
1357 // Now once again promote all objects to pseudo-static just prior to save.
1358 // 'coreparse' makes all pages in regular dynamic space pseudo-static.
1359 // But since immobile objects store their generation, it must be done at save,
1360 // or else it would have to be done on image restart
1361 // which would require writing to a lot of pages for no reason.
1362 void prepare_immobile_space_for_save()
1364 // Don't use the page attributes now - defrag doesn't update them.
1365 lispobj* obj = (lispobj*)IMMOBILE_SPACE_START;
1366 lispobj* limit = immobile_fixedobj_free_pointer;
1367 while (obj < limit) {
1368 if (other_immediate_lowtag_p(*obj))
1369 assign_generation(obj, PSEUDO_STATIC_GENERATION);
1370 obj += sizetab[widetag_of(*obj)](obj);
1373 obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1374 limit = immobile_space_free_pointer;
1375 for ( varyobj_holes = 0 ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
1376 if (immobile_filler_p(obj)) {
1377 struct code* code = (struct code*)obj;
1378 code->debug_info = varyobj_holes;
1379 varyobj_holes = (lispobj)code;
1380 // 0-fill the unused space.
1381 int nwords = sizetab[widetag_of(*obj)](obj);
1382 memset(code->constants, 0,
1383 (nwords * N_WORD_BYTES) - offsetof(struct code, constants));
1384 } else
1385 assign_generation(obj, PSEUDO_STATIC_GENERATION);
1389 //// Interface
1391 int immobile_space_handle_wp_violation(void* fault_addr)
1393 low_page_index_t page_index = find_immobile_page_index(fault_addr);
1394 if (page_index < 0) return 0;
1396 os_protect((os_vm_address_t)((lispobj)fault_addr & ~(IMMOBILE_CARD_BYTES-1)),
1397 IMMOBILE_CARD_BYTES, OS_VM_PROT_ALL);
1398 if (page_index >= FIRST_VARYOBJ_PAGE) {
1399 // The free pointer can move up or down. Attempting to insist that a WP
1400 // fault not occur above the free pointer (plus some slack) is not
1401 // threadsafe, so allow it anywhere. More strictness could be imparted
1402 // by tracking the max value attained by the free pointer.
1403 __sync_or_and_fetch(&varyobj_page_touched_bits[(page_index-FIRST_VARYOBJ_PAGE)/32],
1404 1 << (page_index & 31));
1405 } else {
1406 // FIXME: a single bitmap of touched bits would make more sense,
1407 // and the _CLEARED flag doesn't achieve much if anything.
1408 if (!(fixedobj_pages[page_index].attr.parts.flags
1409 & (WRITE_PROTECT|WRITE_PROTECT_CLEARED)))
1410 return 0;
1411 SET_WP_FLAG(page_index, WRITE_PROTECT_CLEARED);
1413 return 1;
1416 // Find the object that encloses pointer.
1417 static int page_attributes_valid = 1; // For verify_space() after defrag
1418 lispobj *
1419 search_immobile_space(void *pointer)
1421 lispobj *start;
1423 if ((lispobj)pointer >= IMMOBILE_SPACE_START
1424 && pointer < (void*)immobile_space_free_pointer) {
1425 low_page_index_t page_index = find_immobile_page_index(pointer);
1426 if ((lispobj)pointer >= IMMOBILE_VARYOBJ_SUBSPACE_START) {
1427 if (page_attributes_valid) {
1428 start = (lispobj*)varyobj_scan_start(page_index);
1429 if (start > (lispobj*)pointer) return NULL;
1430 } else {
1431 start = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1433 lispobj* found = gc_search_space(start, pointer);
1434 return (found && immobile_filler_p(found)) ? 0 : found;
1435 } else if (pointer < (void*)immobile_fixedobj_free_pointer) {
1436 char *page_base = (char*)((lispobj)pointer & ~(IMMOBILE_CARD_BYTES-1));
1437 if (page_attributes_valid) {
1438 int spacing = page_obj_align(page_index) << WORD_SHIFT;
1439 int index = ((char*)pointer - page_base) / spacing;
1440 char *begin = page_base + spacing * index;
1441 char *end = begin + (page_obj_size(page_index) << WORD_SHIFT);
1442 if ((char*)pointer < end) return (lispobj*)begin;
1443 } else {
1444 return gc_search_space((lispobj*)page_base, pointer);
1448 return NULL;
1451 // For coalescing holes, we need to scan backwards, which is done by
1452 // looking backwards for a page that contains the start of a
1453 // block of objects one of which must abut 'obj'.
1454 lispobj* find_preceding_object(lispobj* obj)
1456 int page = find_immobile_page_index(obj);
1457 while (1) {
1458 int offset = varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE];
1459 if (offset) { // 0 means the page is empty.
1460 lispobj* start = varyobj_scan_start(page);
1461 if (start < obj) { // Scan from here forward
1462 while (1) {
1463 lispobj* end = start + sizetab[widetag_of(*start)](start);
1464 if (end == obj) return start;
1465 gc_assert(end < obj);
1466 start = end;
1470 if (page == FIRST_VARYOBJ_PAGE) {
1471 gc_assert(obj == low_page_address(FIRST_VARYOBJ_PAGE));
1472 return 0; // Predecessor does not exist
1474 --page;
1478 #include "genesis/vector.h"
1479 #include "genesis/instance.h"
1480 lispobj alloc_layout(lispobj slots)
1482 struct vector* v = VECTOR(slots);
1483 // If INSTANCE_DATA_START is 0, subtract 1 word for the header.
1484 // If 1, subtract 2 words: 1 for the header and 1 for the layout.
1485 if (fixnum_value(v->length) != (LAYOUT_SIZE - INSTANCE_DATA_START - 1))
1486 lose("bad arguments to alloc_layout");
1487 struct instance* l = (struct instance*)
1488 alloc_immobile_obj(MAKE_ATTR(LAYOUT_ALIGN / N_WORD_BYTES,
1489 CEILING(LAYOUT_SIZE,2),
1491 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1492 (LAYOUT_OF_LAYOUT << 32) |
1493 #endif
1494 (LAYOUT_SIZE-1)<<8 | INSTANCE_WIDETAG,
1495 &layout_page_hint);
1496 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1497 l->slots[0] = LAYOUT_OF_LAYOUT;
1498 #endif
1499 memcpy(&l->slots[INSTANCE_DATA_START], v->data,
1500 (LAYOUT_SIZE - INSTANCE_DATA_START - 1)*N_WORD_BYTES);
1502 // Possible efficiency win: make the "wasted" bytes after the layout into a
1503 // simple unboxed array so that heap-walking can skip in one step.
1504 // Probably only a performance issue for MAP-ALLOCATED-OBJECTS,
1505 // since scavenging know to skip by the object alignment anyway.
1506 return make_lispobj(l, INSTANCE_POINTER_LOWTAG);
1509 #include "genesis/symbol.h"
1510 lispobj alloc_sym(lispobj name)
1512 // While there are different "kinds" of symbols in the defragmentation
1513 // logic, we don't distinguish them when allocating,
1514 // on the theory that contiguous allocations are preferable anyway.
1515 struct symbol* s = (struct symbol*)
1516 alloc_immobile_obj(MAKE_ATTR(CEILING(SYMBOL_SIZE,2), // spacing
1517 CEILING(SYMBOL_SIZE,2), // size
1519 (SYMBOL_SIZE-1)<<8 | SYMBOL_WIDETAG,
1520 &symbol_page_hint);
1521 s->value = UNBOUND_MARKER_WIDETAG;
1522 s->hash = 0;
1523 s->info = NIL;
1524 s->name = name;
1525 s->package = NIL;
1526 return make_lispobj(s, OTHER_POINTER_LOWTAG);
1529 #include "genesis/fdefn.h"
1530 lispobj alloc_fdefn(lispobj name)
1532 struct fdefn* f = (struct fdefn*)
1533 alloc_immobile_obj(MAKE_ATTR(CEILING(FDEFN_SIZE,2), // spacing
1534 CEILING(FDEFN_SIZE,2), // size
1536 (FDEFN_SIZE-1)<<8 | FDEFN_WIDETAG,
1537 &fdefn_page_hint);
1538 f->name = name;
1539 f->fun = NIL;
1540 f->raw_addr = 0;
1541 return make_lispobj(f, OTHER_POINTER_LOWTAG);
1544 #if defined(LISP_FEATURE_IMMOBILE_CODE) && defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER)
1545 #include "genesis/funcallable-instance.h"
1546 #define GF_SIZE (sizeof(struct funcallable_instance)/sizeof(lispobj)+2) /* = 6 */
1547 lispobj alloc_generic_function(lispobj slots)
1549 // GFs have no C header file to represent the layout, which is 6 words:
1550 // header, entry-point, fin-function, slots, raw data (x2)
1551 lispobj* obj = (lispobj*)
1552 alloc_immobile_obj(MAKE_ATTR(CEILING(GF_SIZE,2), // spacing
1553 CEILING(GF_SIZE,2), // size
1555 // 5 payload words following the header
1556 ((GF_SIZE-1)<<8) | FUNCALLABLE_INSTANCE_WIDETAG,
1557 // KLUDGE: same page attributes as symbols,
1558 // so use the same hint.
1559 &symbol_page_hint);
1560 ((struct funcallable_instance*)obj)->info[0] = slots;
1561 ((struct funcallable_instance*)obj)->trampoline = (lispobj)(obj + 4);
1562 return make_lispobj(obj, FUN_POINTER_LOWTAG);
1564 #endif
1566 #ifdef LISP_FEATURE_IMMOBILE_CODE
1567 //// Defragmentation
1569 static struct {
1570 char* start;
1571 int n_bytes;
1572 } fixedobj_tempspace, varyobj_tempspace;
1574 // Given an adddress in the target core, return the equivalent
1575 // physical address to read or write during defragmentation
1576 static lispobj* tempspace_addr(void* address)
1578 int byte_index = (char*)address - (char*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1579 gc_assert(immobile_space_p((lispobj)address));
1580 if (byte_index < 0) { // fixedobj subspace
1581 if (fixedobj_tempspace.n_bytes == 0) return address;
1582 byte_index = (char*)address - (char*)IMMOBILE_SPACE_START;
1583 gc_assert(byte_index < fixedobj_tempspace.n_bytes);
1584 return (void*)(fixedobj_tempspace.start + byte_index);
1585 } else { // varyobj subspace
1586 gc_assert(byte_index < varyobj_tempspace.n_bytes);
1587 return (void*)(varyobj_tempspace.start + byte_index);
1591 /* Search for an object during defragmentation */
1592 static lispobj* defrag_search_varyobj_subspace(lispobj addr)
1594 low_page_index_t page = find_immobile_page_index((void*)(long)addr);
1595 lispobj *where = varyobj_scan_start(page);
1596 size_t count;
1597 do {
1598 if (immobile_filler_p(where)) {
1599 count = sizetab[widetag_of(*where)](where);
1600 } else {
1601 gc_assert(forwarding_pointer_p(where));
1602 lispobj *forwarded_obj = native_pointer(forwarding_pointer_value(where));
1603 lispobj *temp_obj = tempspace_addr(forwarded_obj);
1604 count = sizetab[widetag_of(*temp_obj)](temp_obj);
1605 if ((lispobj*)(uword_t)addr < where+count) {
1606 int __attribute__((unused)) widetag = widetag_of(*temp_obj);
1607 gc_assert(widetag == CODE_HEADER_WIDETAG ||
1608 widetag == FDEFN_WIDETAG ||
1609 widetag == FUNCALLABLE_INSTANCE_WIDETAG);
1610 return where;
1613 } while ((where += count) <= (lispobj*)(uword_t)addr);
1614 lose("Can't find jump target");
1617 static void adjust_words(lispobj *where, sword_t n_words)
1619 int i;
1620 for (i=0;i<n_words;++i) {
1621 lispobj ptr = where[i];
1622 if (is_lisp_pointer(ptr) && forwarding_pointer_p(native_pointer(ptr)))
1623 where[i] = forwarding_pointer_value(native_pointer(ptr));
1627 static lispobj adjust_fun_entrypoint(lispobj raw_addr)
1629 // closure tramp and fin tramp don't have a simple-fun header.
1630 // Do not examine the word where the header would be,
1631 // since it could confuse adjust_words() by having a bit pattern
1632 // resembling a FP. (It doesn't, but better safe than sorry)
1633 if (raw_addr < ASM_ROUTINES_END) return raw_addr;
1634 lispobj simple_fun = raw_addr - FUN_RAW_ADDR_OFFSET;
1635 adjust_words(&simple_fun, 1);
1636 return simple_fun + FUN_RAW_ADDR_OFFSET;
1639 /// Fixup the fdefn at 'where' based on it moving by 'displacement'.
1640 /// 'fdefn_old' is needed for computing the pre-fixup callee if the
1641 /// architecture uses a call-relative instruction.
1642 static void adjust_fdefn_entrypoint(lispobj* where, int displacement,
1643 struct fdefn* fdefn_old)
1645 struct fdefn* fdefn = (struct fdefn*)where;
1646 int callee_adjust = 0;
1647 // Get the tagged object referred to by the fdefn_raw_addr.
1648 lispobj callee_old = fdefn_raw_referent(fdefn_old);
1649 // If it's the undefined function trampoline, or the referent
1650 // did not move, then the callee_adjust stays 0.
1651 // Otherwise we adjust the rel32 field by the change in callee address.
1652 if (callee_old && forwarding_pointer_p(native_pointer(callee_old))) {
1653 lispobj callee_new = forwarding_pointer_value(native_pointer(callee_old));
1654 callee_adjust = callee_new - callee_old;
1656 #ifdef LISP_FEATURE_X86_64
1657 *(int*)((char*)&fdefn->raw_addr + 1) += callee_adjust - displacement;
1658 #else
1659 #error "Can't adjust fdefn_raw_addr for this architecture"
1660 #endif
1663 // Fix the layout of OBJ, and return the layout's address in tempspace.
1664 struct layout* fix_object_layout(lispobj* obj)
1666 // This works on instances, funcallable instances (and/or closures)
1667 // but the latter only if the layout is in the header word.
1668 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1669 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG
1670 || widetag_of(*obj) == FUNCALLABLE_INSTANCE_WIDETAG
1671 || widetag_of(*obj) == CLOSURE_WIDETAG);
1672 #else
1673 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1674 #endif
1675 lispobj layout = instance_layout(obj);
1676 if (layout == 0) return 0;
1677 if (forwarding_pointer_p(native_pointer(layout))) { // usually
1678 layout = forwarding_pointer_value(native_pointer(layout));
1679 set_instance_layout(obj, layout);
1681 struct layout* native_layout = (struct layout*)tempspace_addr(LAYOUT(layout));
1682 gc_assert(widetag_of(native_layout->header) == INSTANCE_WIDETAG);
1683 gc_assert(instance_layout((lispobj*)native_layout) == LAYOUT_OF_LAYOUT);
1684 return native_layout;
1687 static lispobj follow_fp(lispobj ptr)
1689 if (forwarding_pointer_p(native_pointer(ptr)))
1690 return forwarding_pointer_value(native_pointer(ptr));
1691 else
1692 return ptr;
1695 /// It's tricky to try to use the scavtab[] functions for fixing up moved
1696 /// objects, because scavenger functions might invoke transport functions.
1697 /// The best approach is to do an explicit switch over all object types.
1698 #include "genesis/hash-table.h"
1699 static void fixup_space(lispobj* where, size_t n_words)
1701 lispobj* end = where + n_words;
1702 lispobj header_word;
1703 int widetag;
1704 long size;
1705 int static_space_p = ((lispobj)where == STATIC_SPACE_START);
1706 struct code* code;
1708 while (where < end) {
1709 gc_assert(!forwarding_pointer_p(where));
1710 header_word = *where;
1711 if (is_cons_half(header_word)) {
1712 adjust_words(where, 2); // A cons.
1713 where += 2;
1714 continue;
1716 widetag = widetag_of(header_word);
1717 size = sizetab[widetag](where);
1718 switch (widetag) {
1719 default:
1720 if (!unboxed_obj_widetag_p(widetag))
1721 lose("Unhandled widetag in fixup_space: %p\n", (void*)header_word);
1722 break;
1723 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1724 case FUNCALLABLE_INSTANCE_WIDETAG:
1725 #endif
1726 case INSTANCE_WIDETAG:
1727 instance_scan(adjust_words, where+1,
1728 instance_length(header_word) | 1,
1729 fix_object_layout(where)->bitmap);
1730 break;
1731 case CODE_HEADER_WIDETAG:
1732 // Fixup the constant pool.
1733 adjust_words(where+1, code_header_words(header_word)-1);
1734 // Fixup all embedded simple-funs
1735 code = (struct code*)where;
1736 for_each_simple_fun(i, f, code, 1, {
1737 f->self = adjust_fun_entrypoint(f->self);
1738 adjust_words(SIMPLE_FUN_SCAV_START(f), SIMPLE_FUN_SCAV_NWORDS(f));
1740 if (code->fixups)
1741 fixup_immobile_refs(follow_fp, code->fixups, code);
1742 break;
1743 case CLOSURE_WIDETAG:
1744 where[1] = adjust_fun_entrypoint(where[1]);
1745 // FALLTHROUGH_INTENDED
1746 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1747 case FUNCALLABLE_INSTANCE_WIDETAG:
1748 #endif
1749 // skip the trampoline word at where[1]
1750 adjust_words(where+2, size-2);
1751 break;
1752 case FDEFN_WIDETAG:
1753 adjust_words(where+1, 2);
1754 // If fixed-size objects (hence FDEFNs) are movable, then fixing the
1755 // raw address can not be done here, because it is impossible to compute
1756 // the absolute jump target - we don't know what the fdefn's original
1757 // address was to compute a pc-relative address. So we do those while
1758 // permuting the FDEFNs. But because static fdefns do not move,
1759 // we do process their raw address slot here.
1760 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
1761 if (static_space_p)
1762 #endif
1763 adjust_fdefn_entrypoint(where, 0, (struct fdefn*)where);
1764 break;
1766 // Special case because we might need to mark hashtables
1767 // as needing rehash.
1768 case SIMPLE_VECTOR_WIDETAG:
1769 if ((HeaderValue(header_word) & 0xFF) == subtype_VectorValidHashing) {
1770 struct vector* v = (struct vector*)where;
1771 lispobj* data = v->data;
1772 gc_assert(v->length > 0 &&
1773 lowtag_of(data[0]) == INSTANCE_POINTER_LOWTAG &&
1774 !(fixnum_value(v->length) & 1)); // length must be even
1775 boolean needs_rehash = 0;
1776 int i;
1777 for (i = fixnum_value(v->length)-1 ; i>=0 ; --i) {
1778 lispobj ptr = data[i];
1779 if (is_lisp_pointer(ptr) && forwarding_pointer_p(native_pointer(ptr))) {
1780 data[i] = forwarding_pointer_value(native_pointer(ptr));
1781 needs_rehash = 1;
1784 if (needs_rehash) {
1785 struct hash_table *ht = (struct hash_table*)native_pointer(v->data[0]);
1786 ht->needs_rehash_p = T;
1788 break;
1789 } else {
1790 // FALLTHROUGH_INTENDED
1792 // All the other array header widetags.
1793 case SIMPLE_ARRAY_WIDETAG:
1794 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
1795 case COMPLEX_CHARACTER_STRING_WIDETAG:
1796 #endif
1797 case COMPLEX_BASE_STRING_WIDETAG:
1798 case COMPLEX_VECTOR_NIL_WIDETAG:
1799 case COMPLEX_BIT_VECTOR_WIDETAG:
1800 case COMPLEX_VECTOR_WIDETAG:
1801 case COMPLEX_ARRAY_WIDETAG:
1802 // And the other entirely boxed objects.
1803 case SYMBOL_WIDETAG:
1804 case VALUE_CELL_WIDETAG:
1805 case WEAK_POINTER_WIDETAG:
1806 case RATIO_WIDETAG:
1807 case COMPLEX_WIDETAG:
1808 // Use the sizing functions for generality.
1809 // Symbols can contain strange header bytes,
1810 // and vectors might have a padding word, etc.
1811 adjust_words(where+1, size-1);
1812 break;
1814 where += size;
1818 int* immobile_space_reloc_index;
1819 int* immobile_space_relocs;
1821 static int calc_n_pages(int n_objects, int words_per_object)
1823 words_per_object = CEILING(words_per_object, 2);
1824 int objects_per_page = WORDS_PER_PAGE / words_per_object;
1825 return (n_objects + objects_per_page - 1) / objects_per_page;
1828 // Take and return an untagged pointer, or 0 if the object did not survive GC.
1829 static lispobj* get_load_address(lispobj* old)
1831 if (forwarding_pointer_p(old))
1832 return native_pointer(forwarding_pointer_value(old));
1833 gc_assert(immobile_filler_p(old));
1834 return 0;
1837 // This does not accept (SIMPLE-ARRAY NIL (*))
1838 // (You'd have a pretty bad time trying making a symbol like that)
1839 static int schar(struct vector* string, int index)
1841 #ifdef LISP_FEATURE_SB_UNICODE
1842 if (widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG)
1843 return ((int*)string->data)[index];
1844 #endif
1845 return ((char*)string->data)[index];
1848 #include "genesis/package.h"
1849 #define N_SYMBOL_KINDS 4
1851 // Return an integer 0..3 telling which block of symbols to relocate 'sym' into.
1852 // This is the same as the "symbol kind" in the allocator.
1853 // 0 = uninterned, 1 = keyword, 2 = other interned, 3 = special var
1854 static int classify_symbol(lispobj* obj)
1856 struct symbol* symbol = (struct symbol*)obj;
1857 if (symbol->package == NIL) return 0;
1858 struct vector* package_name = (struct vector*)
1859 native_pointer(((struct package*)native_pointer(symbol->package))->_name);
1860 if (widetag_of(package_name->header) == SIMPLE_BASE_STRING_WIDETAG
1861 && !strcmp((char*)package_name->data, "KEYWORD"))
1862 return 1;
1863 struct vector* symbol_name = VECTOR(symbol->name);
1864 if (symbol_name->length >= make_fixnum(2) &&
1865 schar(symbol_name, 0) == '*' &&
1866 schar(symbol_name, fixnum_value(symbol_name->length)-1) == '*')
1867 return 3;
1868 return 2;
1871 static char* compute_defrag_start_address()
1873 // For technical reasons, objects on the first few pages created by genesis
1874 // must never move at all. So figure out where the end of that subspace is.
1875 lispobj* obj = (lispobj*)IMMOBILE_SPACE_START;
1876 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1877 while (instance_layout(obj) != LAYOUT_OF_PACKAGE) {
1878 obj = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1879 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1881 // Now find a page that does NOT have a package.
1882 do {
1883 obj = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1884 } while (widetag_of(*obj) == INSTANCE_WIDETAG
1885 && instance_layout(obj) == LAYOUT_OF_PACKAGE);
1886 return (char*)obj;
1889 void defrag_immobile_space(int* components, boolean verbose)
1891 // Find the starting address of fixed-size objects that will undergo defrag.
1892 // Never move the first few pages of LAYOUTs or PACKAGEs created by genesis.
1893 // If codegen becomes smarter, things like layout of FUNCTION and some
1894 // some others can be used as immediate constants in compiled code.
1895 // With initial packages, it's mainly a debugging convenience that they not move.
1896 char* defrag_base = compute_defrag_start_address();
1897 low_page_index_t page_index = find_immobile_page_index(defrag_base);
1898 lispobj* addr;
1899 int i;
1901 // Count the number of symbols, fdefns, and layouts that will be relocated
1902 unsigned int obj_type_histo[64], sym_kind_histo[4];
1903 bzero(obj_type_histo, sizeof obj_type_histo);
1904 bzero(sym_kind_histo, sizeof sym_kind_histo);
1906 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
1907 for ( ; page_index <= max_used_fixedobj_page ; ++page_index) {
1908 int obj_spacing = page_obj_align(page_index) << WORD_SHIFT;
1909 if (obj_spacing) {
1910 lispobj* obj = low_page_address(page_index);
1911 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1912 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1913 lispobj word = *obj;
1914 if (!fixnump(word)) {
1915 if (widetag_of(word) == SYMBOL_WIDETAG)
1916 ++sym_kind_histo[classify_symbol(obj)];
1917 else
1918 ++obj_type_histo[widetag_of(word)/4];
1923 gc_assert(obj_type_histo[INSTANCE_WIDETAG/4]);
1925 // Calculate space needed for fixedobj pages after defrag.
1926 // page order is: layouts, fdefns, GFs, symbols
1927 int n_layout_pages = calc_n_pages(obj_type_histo[INSTANCE_WIDETAG/4],
1928 LAYOUT_ALIGN / N_WORD_BYTES);
1929 int n_fdefn_pages = calc_n_pages(obj_type_histo[FDEFN_WIDETAG/4], FDEFN_SIZE);
1930 int n_fin_pages = calc_n_pages(obj_type_histo[FUNCALLABLE_INSTANCE_WIDETAG/4],
1931 6); // KLUDGE
1932 #if !(defined(LISP_FEATURE_IMMOBILE_CODE) && defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER))
1933 gc_assert(n_fin_pages == 0);
1934 #endif
1935 char* layout_alloc_ptr = defrag_base;
1936 char* fdefn_alloc_ptr = layout_alloc_ptr + n_layout_pages * IMMOBILE_CARD_BYTES;
1937 char* fin_alloc_ptr = fdefn_alloc_ptr + n_fdefn_pages * IMMOBILE_CARD_BYTES;
1938 char* symbol_alloc_ptr[N_SYMBOL_KINDS+1];
1939 symbol_alloc_ptr[0] = fin_alloc_ptr + n_fin_pages * IMMOBILE_CARD_BYTES;
1940 for (i=0; i<N_SYMBOL_KINDS ; ++i)
1941 symbol_alloc_ptr[i+1] = symbol_alloc_ptr[i]
1942 + calc_n_pages(sym_kind_histo[i], SYMBOL_SIZE) * IMMOBILE_CARD_BYTES;
1943 char* ending_alloc_ptr = symbol_alloc_ptr[N_SYMBOL_KINDS];
1945 fixedobj_tempspace.n_bytes = ending_alloc_ptr - (char*)IMMOBILE_SPACE_START;
1946 fixedobj_tempspace.start = calloc(fixedobj_tempspace.n_bytes, 1);
1947 // Copy the first few pages (the permanent pages) from immobile space
1948 // into the temporary copy, so that tempspace_addr()
1949 // does not have to return the unadjusted addr if below defrag_base.
1950 memcpy(fixedobj_tempspace.start, (char*)IMMOBILE_SPACE_START,
1951 (lispobj)defrag_base - IMMOBILE_SPACE_START);
1952 #endif
1954 // Compute where each code component will be moved to.
1955 int n_code_components = 0;
1956 for (i=0 ; components[i*2] ; ++i) {
1957 addr = (lispobj*)(long)components[i*2];
1958 gc_assert(lowtag_of((lispobj)addr) == OTHER_POINTER_LOWTAG);
1959 addr = native_pointer((lispobj)addr);
1960 int widetag = widetag_of(*addr);
1961 lispobj new_vaddr = 0;
1962 // FIXME: generalize
1963 gc_assert(widetag == CODE_HEADER_WIDETAG);
1964 if (!immobile_filler_p(addr)) {
1965 ++n_code_components;
1966 new_vaddr = IMMOBILE_VARYOBJ_SUBSPACE_START + varyobj_tempspace.n_bytes;
1967 varyobj_tempspace.n_bytes += sizetab[widetag](addr) << WORD_SHIFT;
1969 components[i*2+1] = new_vaddr;
1971 varyobj_tempspace.start = calloc(varyobj_tempspace.n_bytes, 1);
1973 if (verbose)
1974 printf("%d+%d+%d+%d objects... ",
1975 obj_type_histo[INSTANCE_WIDETAG/4],
1976 obj_type_histo[FDEFN_WIDETAG/4],
1977 (sym_kind_histo[0]+sym_kind_histo[1]+
1978 sym_kind_histo[2]+sym_kind_histo[3]),
1979 n_code_components);
1981 // Permute varyobj space into tempspace and deposit forwarding pointers.
1982 lispobj new_vaddr;
1983 for (i=0 ; components[i*2] ; ++i) {
1984 if ((new_vaddr = components[i*2+1]) != 0) {
1985 addr = native_pointer(components[i*2]);
1986 memcpy(tempspace_addr((void*)new_vaddr), addr,
1987 sizetab[widetag_of(*addr)](addr) << WORD_SHIFT);
1988 int displacement = new_vaddr - (lispobj)addr;
1989 switch (widetag_of(*addr)) {
1990 case CODE_HEADER_WIDETAG:
1991 for_each_simple_fun(index, fun, (struct code*)addr, 1, {
1992 set_forwarding_pointer((lispobj*)fun,
1993 make_lispobj((char*)fun + displacement,
1994 FUN_POINTER_LOWTAG));
1996 break;
1998 set_forwarding_pointer(addr,
1999 make_lispobj((void*)new_vaddr,
2000 OTHER_POINTER_LOWTAG));
2004 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2005 // Permute fixed-sized object pages and deposit forwarding pointers.
2006 for ( page_index = find_immobile_page_index(defrag_base) ;
2007 page_index <= max_used_fixedobj_page ; ++page_index) {
2008 int obj_spacing = page_obj_align(page_index) << WORD_SHIFT;
2009 if (!obj_spacing) continue;
2010 lispobj* obj = low_page_address(page_index);
2011 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
2012 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
2013 lispobj word = *obj;
2014 if (fixnump(word)) continue;
2015 char** alloc_ptr;
2016 int lowtag = OTHER_POINTER_LOWTAG;
2017 int widetag = widetag_of(word);
2018 switch (widetag) {
2019 case INSTANCE_WIDETAG:
2020 alloc_ptr = &layout_alloc_ptr;
2021 lowtag = INSTANCE_POINTER_LOWTAG;
2022 break;
2023 case FUNCALLABLE_INSTANCE_WIDETAG:
2024 alloc_ptr = &fin_alloc_ptr;
2025 lowtag = FUN_POINTER_LOWTAG;
2026 break;
2027 case FDEFN_WIDETAG:
2028 alloc_ptr = &fdefn_alloc_ptr;
2029 break;
2030 case SYMBOL_WIDETAG:
2031 alloc_ptr = &symbol_alloc_ptr[classify_symbol(obj)];
2032 break;
2033 default:
2034 lose("Unexpected widetag");
2036 lispobj* new = (lispobj*)*alloc_ptr;
2037 lispobj end = (lispobj)new + obj_spacing;
2038 #define ALIGN_MASK (IMMOBILE_CARD_BYTES - 1)
2039 if ((end & ALIGN_MASK) < ((lispobj)new & ALIGN_MASK) // wrapped
2040 && (end & ALIGN_MASK) != 0) // ok if exactly on the boundary
2041 new = (lispobj*)(end & ~ALIGN_MASK); // snap to page
2042 #undef ALIGN_MASK
2043 memcpy(tempspace_addr(new), obj, sizetab[widetag](obj) << WORD_SHIFT);
2044 set_forwarding_pointer(obj, make_lispobj(new, lowtag));
2045 *alloc_ptr = (char*)new + obj_spacing;
2048 #ifdef LISP_FEATURE_X86_64
2049 // Fixup JMP offset in fdefns, and self pointers in funcallable instances.
2050 // The former can not be done in the same pass as space permutation,
2051 // because we don't know the order in which a generic function and its
2052 // related fdefn will be reached. Were this attempted in a single pass,
2053 // it could miss a GF that will be moved after the fdefn is moved.
2054 // And it can't be done in fixup_space() because that does not know the
2055 // original address of each fdefn, so can't compute the absolute callee.
2056 for ( page_index = find_immobile_page_index(defrag_base) ;
2057 page_index <= max_used_fixedobj_page ; ++page_index) {
2058 int obj_spacing = page_obj_align(page_index) << WORD_SHIFT;
2059 if (!obj_spacing) continue;
2060 lispobj* obj = low_page_address(page_index);
2061 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
2062 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
2063 if (fixnump(*obj)) continue;
2064 gc_assert(forwarding_pointer_p(obj));
2065 lispobj* new = native_pointer(forwarding_pointer_value(obj));
2066 switch (widetag_of(*tempspace_addr(new))) {
2067 case FDEFN_WIDETAG:
2068 // Fix displacement in JMP or CALL instruction.
2069 adjust_fdefn_entrypoint(tempspace_addr(new),
2070 (char*)new - (char*)obj,
2071 (struct fdefn*)obj);
2072 break;
2073 case FUNCALLABLE_INSTANCE_WIDETAG:
2074 tempspace_addr(new)[1] = (lispobj)(new + 4);
2075 break;
2079 #endif /* LISP_FEATURE_X86_64 */
2080 #endif /* DEFRAGMENT_FIXEDOBJ_SUBSPACE */
2082 #ifdef LISP_FEATURE_X86_64
2083 // Fix displacements in JMP and CALL instructions in code objects.
2084 // There are 2 arrays in use:
2085 // - the relocs[] array contains the address of any machine instruction
2086 // that needs to be altered on account of space relocation.
2087 // - the reloc_index[] array identifes the code component each reloc belongs to.
2088 // It is an array of pairs:
2089 // comp_ptr1, index1, comp_ptr2, index2 ... comp_ptrN, indexN, 0, index_max
2090 // The index following a component specifies the starting index within the
2091 // relocs[] array of the first reloc belonging to the respective component.
2092 // The ending reloc can be deduced from the next component's first reloc.
2093 for (i = 0 ; immobile_space_reloc_index[i*2] ; ++i) {
2094 lispobj code = immobile_space_reloc_index[i*2] - OTHER_POINTER_LOWTAG;
2095 lispobj load_addr;
2096 if (code >= READ_ONLY_SPACE_START && code < READ_ONLY_SPACE_END)
2097 load_addr = code; // This code can not be moved or GCed.
2098 else
2099 load_addr = (lispobj)get_load_address((lispobj*)code);
2100 if (!load_addr) continue; // Skip code that was dropped by GC
2101 int reloc_index = immobile_space_reloc_index[i*2+1];
2102 int end_reloc_index = immobile_space_reloc_index[i*2+3];
2103 for ( ; reloc_index < end_reloc_index ; ++reloc_index ) {
2104 unsigned char* inst_addr = (unsigned char*)(long)immobile_space_relocs[reloc_index];
2105 gc_assert(*inst_addr == 0xE8 || *inst_addr == 0xE9);
2106 unsigned int target_addr = (int)(long)inst_addr + 5 + *(int*)(inst_addr+1);
2107 int target_adjust = 0;
2108 // Both this code and the jumped-to code can move.
2109 // For this component, adjust by the displacement by (old - new).
2110 // If the jump target moved, also adjust by its (new - old).
2111 // The target address can point to one of:
2112 // - an FDEFN raw addr slot (fixedobj subspace)
2113 // - funcallable-instance with self-contained trampoline (ditto)
2114 // - a simple-fun that was statically linked (varyobj subspace)
2115 if (immobile_space_p(target_addr)) {
2116 lispobj *obj = target_addr < IMMOBILE_VARYOBJ_SUBSPACE_START
2117 ? search_immobile_space((void*)(uword_t)target_addr)
2118 : defrag_search_varyobj_subspace(target_addr);
2119 if (forwarding_pointer_p(obj))
2120 target_adjust = (int)((char*)native_pointer(forwarding_pointer_value(obj))
2121 - (char*)obj);
2123 // If the instruction to fix has moved, then adjust for
2124 // its new address, and perform the fixup in tempspace.
2125 // Otherwise perform the fixup where the instruction is now.
2126 char* fixup_loc = (immobile_space_p((lispobj)inst_addr) ?
2127 (char*)tempspace_addr(inst_addr - code + load_addr) :
2128 (char*)inst_addr) + 1;
2129 *(int*)fixup_loc += target_adjust + (code - load_addr);
2132 #endif
2133 free(immobile_space_relocs);
2134 free(immobile_space_reloc_index);
2136 // Fix Lisp pointers in static, immobile, and dynamic spaces
2137 fixup_space((lispobj*)STATIC_SPACE_START,
2138 static_space_free_pointer - (lispobj*)STATIC_SPACE_START);
2140 // Objects in immobile space are physically at 'tempspace',
2141 // but logically at their natural address. Perform fixups
2142 // at their current physical address.
2143 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2144 fixup_space((lispobj*)fixedobj_tempspace.start,
2145 fixedobj_tempspace.n_bytes >> WORD_SHIFT);
2146 #else
2147 fixup_space((lispobj*)IMMOBILE_SPACE_START,
2148 IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE >> WORD_SHIFT);
2149 #endif
2150 fixup_space((lispobj*)varyobj_tempspace.start,
2151 varyobj_tempspace.n_bytes >> WORD_SHIFT);
2153 // Dynamic space
2154 // We can safely ignore allocation region boundaries.
2155 fixup_space(current_dynamic_space,
2156 (lispobj*)get_alloc_pointer() - current_dynamic_space);
2158 // Copy the spaces back where they belong.
2160 // Fixed-size objects: don't copy below the defrag_base - the first few
2161 // pages are totally static in regard to both lifetime and placement.
2162 // (It would "work" to copy them back - since they were copied into
2163 // the temp space, but it's just wasting time to do so)
2164 lispobj old_free_ptr;
2165 lispobj free_ptr;
2166 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2167 int n_static_bytes = ((lispobj)defrag_base - IMMOBILE_SPACE_START);
2168 memcpy((char*)defrag_base,
2169 fixedobj_tempspace.start + n_static_bytes,
2170 fixedobj_tempspace.n_bytes - n_static_bytes);
2171 // Zero-fill the unused remainder
2172 old_free_ptr = (lispobj)immobile_fixedobj_free_pointer;
2173 free_ptr = IMMOBILE_SPACE_START + fixedobj_tempspace.n_bytes;
2174 bzero((char*)free_ptr, old_free_ptr - free_ptr);
2175 immobile_fixedobj_free_pointer = (lispobj*)free_ptr;
2176 #endif
2178 // Variable-size object pages.
2179 memcpy((char*)IMMOBILE_VARYOBJ_SUBSPACE_START,
2180 varyobj_tempspace.start, varyobj_tempspace.n_bytes);
2181 // Zero-fill the unused remainder
2182 old_free_ptr = (lispobj)immobile_space_free_pointer;
2183 free_ptr = IMMOBILE_VARYOBJ_SUBSPACE_START + varyobj_tempspace.n_bytes;
2184 bzero((char*)free_ptr, old_free_ptr - free_ptr);
2185 immobile_space_free_pointer = (lispobj*)free_ptr;
2186 free(components);
2187 #if 0
2188 // It's easy to mess things up, so assert correctness before saving a core.
2189 printf("verifying defrag\n");
2190 page_attributes_valid = 0;
2191 verify_gc();
2192 printf("verify passed\n");
2193 #endif
2194 free(fixedobj_tempspace.start);
2195 free(varyobj_tempspace.start);
2197 #endif
2199 void verify_immobile_page_protection(int keep_gen, int new_gen)
2201 low_page_index_t page;
2202 lispobj* end = immobile_space_free_pointer;
2203 low_page_index_t end_page = find_immobile_page_index((char*)end-1);
2204 lispobj* obj;
2206 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2207 if (!varyobj_page_touched(page)) {
2208 lispobj* page_begin = low_page_address(page);
2209 lispobj* page_end = page_begin + WORDS_PER_PAGE;
2210 // Assert that there are no old->young pointers.
2211 obj = varyobj_scan_start(page);
2212 // Never scan past the free pointer.
2213 // FIXME: It is is supposed to work to scan past the free pointer
2214 // on the last page, but the allocator needs to plop an array header there,
2215 // and sometimes it doesn't.
2216 lispobj* varyobj_free_ptr = immobile_space_free_pointer;
2217 if (page_end > varyobj_free_ptr) page_end = varyobj_free_ptr;
2218 for ( ; obj < page_end ; obj += sizetab[widetag_of(*obj)](obj) ) {
2219 if (!immobile_filler_p(obj)
2220 && varyobj_points_to_younger_p(obj, __immobile_obj_gen_bits(obj),
2221 keep_gen, new_gen,
2222 (char*)page_begin, (char*)page_end))
2223 lose("page WP bit on page %d is wrong\n", page);
2229 // Fixup immediate values that encode Lisp object addresses
2230 // in immobile space.
2231 #include "forwarding-ptr.h"
2232 #ifdef LISP_FEATURE_X86_64
2233 void fixup_immobile_refs(lispobj (*fixup_lispobj)(lispobj),
2234 lispobj fixups, struct code* code)
2236 struct varint_unpacker unpacker;
2237 varint_unpacker_init(&unpacker, fixups);
2238 char* instructions = (char*)((lispobj*)code + code_header_words(code->header));
2239 int prev_loc = 0, loc;
2240 while (varint_unpack(&unpacker, &loc) && loc != 0) {
2241 // For extra compactness, each loc is relative to the prior,
2242 // so that the magnitudes are smaller.
2243 loc += prev_loc;
2244 prev_loc = loc;
2245 int* fixup_where = (int*)(instructions + loc);
2246 lispobj ptr = (lispobj)(*fixup_where);
2247 if (is_lisp_pointer(ptr)) {
2248 lispobj fixed = fixup_lispobj(ptr);
2249 if (fixed != ptr)
2250 *fixup_where = fixed;
2251 } else {
2252 gc_assert(IMMOBILE_SPACE_START <= ptr &&
2253 ptr < (IMMOBILE_SPACE_START+IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE));
2254 // It's an absolute interior pointer. search_immobile_space() works
2255 // at this point, because the page attributes on the pointee's page are valid
2256 lispobj* obj = search_immobile_space((void*)ptr);
2257 if (forwarding_pointer_p(obj)) {
2258 lispobj fpval = forwarding_pointer_value(obj);
2259 *fixup_where = (int)(long)native_pointer(fpval) + (ptr - (lispobj)obj);
2264 #endif
2266 #ifdef VERIFY_PAGE_GENS
2267 void check_fixedobj_page(int page)
2269 // Every page should have a 'gens' mask which exactly reflects
2270 // the aggregate over all objects on that page. Verify that invariant,
2271 // checking all pages, not just the ones below the free pointer.
2272 int genmask, obj_size, obj_spacing, i, all_ok = 1;
2273 lispobj *obj, *limit, header;
2274 int sees_younger = 0;
2276 obj_size = page_obj_size(page);
2277 obj_spacing = page_obj_align(page);
2278 obj = low_page_address(page);
2279 limit = obj + WORDS_PER_PAGE - obj_spacing;
2280 genmask = 0;
2281 if (obj_size == 0) {
2282 for (i=0; i<WORDS_PER_PAGE; ++i)
2283 gc_assert(obj[i]==0);
2284 gc_assert(fixedobj_pages[page].gens ==0);
2285 return;
2287 for ( ; obj <= limit ; obj += obj_spacing ) {
2288 header = *obj;
2289 if (!fixnump(header)) {
2290 int gen = __immobile_obj_gen_bits(obj);
2291 gc_assert(0 <= gen && gen <= PSEUDO_STATIC_GENERATION);
2292 genmask |= 1<<gen;
2293 if (fixedobj_points_to_younger_p(obj, obj_size, gen, 0xff, 0xff))
2294 sees_younger = 1;
2297 // It's not wrong if the gen0 bit is set spuriously, but it should only
2298 // happen at most once, on the first GC after image startup.
2299 // At all other times, the invariant should hold that if the freelist
2300 // indicated that space was available, and the new pointer differs,
2301 // then some gen0 object exists on the page.
2302 // The converse is true because of pseudo-atomicity of the allocator:
2303 // if some thread claimed a hole, then it also updated the freelist.
2304 // If it died before doing the latter, then the object allegedly created
2305 // was never really live, so won't contain any pointers.
2306 if (fixedobj_pages[page].gens != genmask
2307 && fixedobj_pages[page].gens != (genmask|1)) {
2308 fprintf(stderr, "Page #x%x @ %p: stored mask=%x actual=%x\n",
2309 page, low_page_address(page),
2310 fixedobj_pages[page].gens, genmask);
2311 all_ok = 0;
2313 if (fixedobj_page_wp(page) && sees_younger) {
2314 fprintf(stderr, "Page #x%x @ %p: WP is wrong\n",
2315 page, low_page_address(page));
2316 all_ok = 0;
2318 gc_assert(all_ok);
2321 int n_immobile_objects;
2322 int *immobile_objects, *immobile_objects_limit;
2324 int comparator_eq(const void* a, const void* b) {
2325 return *(int*)a - *(int*)b;
2328 // Find the largest item less than or equal.
2329 // (useful for finding the object that contains a given pointer)
2330 int comparator_le(const void* a, const void* b) {
2331 int diff = *(int*)a - *(int*)b;
2332 if (diff <= 0) return diff;
2333 // If looking to the right would see an item strictly greater
2334 // than the sought key, or there is nothing to the right,
2335 // then deem this an exact match.
2336 if (b == (void*)immobile_objects_limit || ((int*)b)[1] > *(int*)a) return 0;
2337 return 1;
2340 // Find the smallest item greater than or equal.
2341 // useful for finding the lowest item at or after a page base address.
2342 int comparator_ge(const void* a, const void* b) {
2343 int diff = *(int*)a - *(int*)b;
2344 if (diff >= 0) return diff;
2345 // If looking to the left would see an item strictly less
2346 // than the sought key, or there is nothing to the left
2347 // then deem this an exact match.
2348 if (b == (void*)immobile_objects || ((int*)b)[-1] < *(int*)a) return 0;
2349 return -1;
2352 void check_varyobj_pages()
2354 // 1. Check that a linear scan sees only valid object headers,
2355 // and that it terminates exactly at IMMOBILE_CODE_FREE_POINTER.
2356 lispobj* obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
2357 lispobj* end = immobile_space_free_pointer;
2358 low_page_index_t end_page = find_immobile_page_index((char*)end-1);
2360 n_immobile_objects = 0;
2361 while (obj < end) {
2362 lispobj word = *obj;
2363 gc_assert(other_immediate_lowtag_p(word));
2364 int n_words = sizetab[widetag_of(word)](obj);
2365 obj += n_words;
2366 ++n_immobile_objects;
2368 gc_assert(obj == end);
2370 // 2. Check that all scan_start_offsets are plausible.
2371 // Begin by collecting all object header locations into an array;
2372 immobile_objects = calloc(n_immobile_objects, sizeof (lispobj));
2373 immobile_objects_limit = immobile_objects + n_immobile_objects - 1;
2374 obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
2375 int i = 0;
2376 while (obj < end) {
2377 immobile_objects[i++] = (lispobj)obj;
2378 lispobj word = *obj;
2379 int n_words = sizetab[widetag_of(word)](obj);
2380 obj += n_words;
2382 // Check that each page's scan start is a known immobile object
2383 // and that it is the right object.
2384 low_page_index_t page;
2385 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2386 lispobj page_addr = (lispobj)low_page_address(page);
2387 int* found_below = bsearch(&page_addr, immobile_objects, n_immobile_objects,
2388 sizeof (int), comparator_le);
2389 int* found_above = bsearch(&page_addr, immobile_objects, n_immobile_objects,
2390 sizeof (int), comparator_ge);
2391 int stored_scan_start = (int)(long)varyobj_scan_start(page);
2392 lispobj* scan_start_obj = (lispobj*)(long)*found_below;
2393 if (scan_start_obj != (lispobj*)(long)stored_scan_start) {
2394 //printf("page %d: found-below=%p stored=%p\n", page, scan_start_obj, stored_scan_start);
2395 while (immobile_filler_p(scan_start_obj)) {
2396 int nwords = sizetab[widetag_of(*scan_start_obj)](scan_start_obj);
2397 // printf("skipping %d words to %p\n", nwords, scan_start_obj + nwords);
2398 scan_start_obj += nwords;
2399 // the stored scan start does not guarantee that it points
2400 // to a non-hole; we only assert that it *probably* does not.
2401 // As such, when computing the "correct" value, we allow
2402 // any value in between the legal bounding values for it.
2403 if ((int)(long)scan_start_obj == stored_scan_start)
2404 break;
2405 // If you hit the free pointer, or run off the page,
2406 // then the page is completely empty.
2407 if (scan_start_obj == immobile_space_free_pointer
2408 || scan_start_obj >= (lispobj*)low_page_address(page+1)) {
2409 scan_start_obj = low_page_address(page+1);
2410 break;
2414 if (scan_start_obj != (lispobj*)(long)stored_scan_start)
2415 lose("page %d: stored_scan_start=%p does not match found %p\n",
2416 page, stored_scan_start, *found_below);
2417 if (found_below != found_above) {
2418 // the object below must touch this page.
2419 // if it didn't, there should be a higher object below.
2420 lispobj* below = (lispobj*)(long)*found_below;
2421 int n_words = sizetab[widetag_of(*below)](below);
2422 lispobj* end = below + n_words;
2423 gc_assert(end > (lispobj*)page_addr);
2426 free(immobile_objects);
2428 // 3. The generation mask for each page is exactly the union
2429 // of generation numbers of object headers on the page.
2430 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2431 if (!varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE])
2432 continue; // page is all holes or never used
2433 obj = varyobj_scan_start(page);
2434 lispobj word = *obj;
2435 int n_words = sizetab[widetag_of(word)](obj);
2436 // Skip the first object if it doesn't start on this page.
2437 if (obj < (lispobj*)low_page_address(page)) obj += n_words;
2438 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
2439 lispobj* freeptr = immobile_space_free_pointer;
2440 if (limit > freeptr) limit = freeptr;
2441 int mask = 0;
2442 for ( ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
2443 int gen = __immobile_obj_gen_bits(obj);
2444 if (immobile_filler_p(obj)) {
2445 gc_assert(gen == 0);
2446 } else {
2447 gc_assert(0 <= gen && gen <= PSEUDO_STATIC_GENERATION);
2448 mask |= 1 << gen;
2451 gc_assert(mask == VARYOBJ_PAGE_GENS(page));
2454 #endif