gencgc: allow operation without SIGSEGV handler
[sbcl.git] / src / runtime / marknsweepgc.c
blob258139abbbc56871fddf303b61bf50bcb0d5400f
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 "var-io.h"
55 #include <stdlib.h>
56 #include <stdio.h>
58 #define FIRST_VARYOBJ_PAGE (IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE/(int)IMMOBILE_CARD_BYTES)
59 #define WORDS_PER_PAGE ((int)IMMOBILE_CARD_BYTES/N_WORD_BYTES)
60 #define DOUBLEWORDS_PER_PAGE (WORDS_PER_PAGE/2)
62 // In case of problems while debugging, this is selectable.
63 #define DEFRAGMENT_FIXEDOBJ_SUBSPACE 1
65 #undef DEBUG
66 #undef VERIFY_PAGE_GENS
68 #ifdef DEBUG
69 # define dprintf(arg) fprintf arg
70 FILE * logfile;
71 #else
72 # define dprintf(arg)
73 #endif
75 // Inclusive bounds on highest in-use pages per subspace.
76 low_page_index_t max_used_fixedobj_page, max_used_varyobj_page;
78 // This table is for objects fixed in size, as opposed to variable-sized.
79 // (Immobile objects are naturally fixed in placement)
80 struct fixedobj_page { // 12 bytes per page
81 union immobile_page_attr {
82 int packed;
83 struct {
84 unsigned char flags;
85 /* space per object in Lisp words. Can exceed obj_size
86 to align on a larger boundary */
87 unsigned char obj_align;
88 unsigned char obj_size; /* in Lisp words, incl. header */
89 /* Which generations have data on this page */
90 unsigned char gens_; // a bitmap
91 } parts;
92 } attr;
93 int free_index; // index is in bytes. 4 bytes
94 short int prior_gc_free_word_index; // index is in words. 2 bytes
95 /* page index of next page with same attributes */
96 short int page_link; // 2 bytes
97 } *fixedobj_pages;
99 unsigned int* immobile_scav_queue;
100 int immobile_scav_queue_head;
101 // Number of items enqueued; can exceed QCAPACITY on overflow.
102 // If overflowed, the queue is unusable until reset.
103 unsigned int immobile_scav_queue_count;
104 #define QCAPACITY (IMMOBILE_CARD_BYTES/sizeof(int))
106 #define gens attr.parts.gens_
108 // These are the high 2 bits of 'flags'
109 #define WRITE_PROTECT 0x80
110 #define WRITE_PROTECT_CLEARED 0x40
112 // Packing and unpacking attributes
113 // the low two flag bits are for write-protect status
114 #define MAKE_ATTR(spacing,size,flags) (((spacing)<<8)|((size)<<16)|flags)
115 #define OBJ_SPACING(attr) ((attr>>8) & 0xFF)
117 // Ignore the write-protect bits and the generations when comparing attributes
118 #define ATTRIBUTES_MATCH_P(page_attr,specified_attr) \
119 ((page_attr & 0xFFFF3F) == specified_attr)
120 #define SET_WP_FLAG(index,flag) \
121 fixedobj_pages[index].attr.parts.flags = (fixedobj_pages[index].attr.parts.flags & 0x3F) | flag
123 #define page_obj_align(i) fixedobj_pages[i].attr.parts.obj_align
124 #define page_obj_size(i) fixedobj_pages[i].attr.parts.obj_size
125 #define set_page_full(i) fixedobj_pages[i].free_index = IMMOBILE_CARD_BYTES
126 #define page_full_p(i) (fixedobj_pages[i].free_index >= (int)IMMOBILE_CARD_BYTES)
127 #define fixedobj_page_wp(i) (fixedobj_pages[i].attr.parts.flags & WRITE_PROTECT)
129 /// Variable-length pages:
131 // Array of inverted write-protect flags, 1 bit per page.
132 unsigned int* varyobj_page_touched_bits;
133 static int n_bitmap_elts; // length of array measured in 'int's
135 // Array of offsets backwards in double-lispwords from the page end
136 // to the lowest-addressed object touching the page. This offset can
137 // point to a hole, but we prefer that it not. If the offset is zero,
138 // the page has no object other than possibly a hole resulting
139 // from a freed object.
140 unsigned short* varyobj_page_scan_start_offset;
142 // Array of page generation masks
143 unsigned char* varyobj_page_header_gens;
144 // Holes to be stuffed back into the managed free list.
145 lispobj varyobj_holes;
147 #define VARYOBJ_PAGE_GENS(x) varyobj_page_header_gens[x-FIRST_VARYOBJ_PAGE]
148 #define varyobj_page_touched(x) \
149 ((varyobj_page_touched_bits[(x-FIRST_VARYOBJ_PAGE)/32] >> (x&31)) & 1)
151 #ifdef VERIFY_PAGE_GENS
152 void check_fixedobj_page(low_page_index_t);
153 void check_varyobj_pages();
154 #endif
156 // Object header: generation byte --| |-- widetag
157 // v v
158 // 0xzzzzzzzz GGzzzzww
159 // arbitrary data -------- ---- length in words
161 // There is a hard constraint on NUM_GENERATIONS, which is currently 8.
162 // (0..5=normal, 6=pseudostatic, 7=scratch)
163 // It could be as high as 16 for 32-bit words (wherein scratch=gen15)
164 // or 32 for 64-bits words (wherein scratch=gen31).
165 // In each case, the VISITED flag bit weight would need to be modified.
166 // Shifting a 1 bit left by the contents of the generation byte
167 // must not overflow a register.
169 #ifdef LISP_FEATURE_LITTLE_ENDIAN
170 static inline void assign_generation(lispobj* obj, generation_index_t gen)
172 ((generation_index_t*)obj)[3] = gen;
174 // Turn a grey node black.
175 static inline void set_visited(lispobj* obj)
177 gc_dcheck(__immobile_obj_gen_bits(obj) == new_space);
178 ((generation_index_t*)obj)[3] |= IMMOBILE_OBJ_VISITED_FLAG;
180 #else
181 #error "Need to define assign_generation() for big-endian"
182 #endif
184 static inline void *
185 low_page_address(low_page_index_t page_num)
187 return ((char*)IMMOBILE_SPACE_START + (page_num * IMMOBILE_CARD_BYTES));
190 //// Variable-length utilities
192 /* Calculate the address where the first object touching this page starts. */
193 static inline lispobj*
194 varyobj_scan_start(low_page_index_t page_index)
196 return (lispobj*)((char*)low_page_address(page_index+1)
197 - varyobj_page_scan_start_offset[page_index - FIRST_VARYOBJ_PAGE]
198 * (2 * N_WORD_BYTES));
201 /* Return the generation mask for objects headers on 'page_index'
202 including at most one object that starts before the page but ends on
203 or after it.
204 If the scan start is within the page, i.e. less than DOUBLEWORDS_PER_PAGE
205 (note that the scan start is measured relative to the page end) then
206 we don't need to OR in the generation byte from an extra object,
207 as all headers on the page are accounted for in the page generation mask.
208 Also an empty page (where scan start is zero) avoids looking
209 at the next page's first object by accident via the same test. */
210 unsigned char varyobj_page_gens_augmented(low_page_index_t page_index)
212 return (varyobj_page_scan_start_offset[page_index - FIRST_VARYOBJ_PAGE] <= DOUBLEWORDS_PER_PAGE
213 ? 0 : (1<<__immobile_obj_generation(varyobj_scan_start(page_index))))
214 | VARYOBJ_PAGE_GENS(page_index);
217 //// Fixed-length object allocator
219 /* Return the index of an immobile page that is probably not totally full,
220 starting with 'hint_page' and wrapping around.
221 'attributes' determine an eligible page.
222 *IMMOBILE-SPACE-FREE-POINTER* is updated to point beyond the found page
223 if it previously did not. */
225 static int get_freeish_page(int hint_page, int attributes)
227 int page = hint_page;
228 lispobj new_free_pointer, old_free_pointer, actual_old;
229 struct symbol * free_pointer_sym;
230 int page_attr_packed;
231 unsigned char best_genmask = 0xff;
232 int best_page = -1;
234 // Speed of this could be improved by keeping a linked list of pages
235 // with any space available, headed by a field in the page struct.
236 // This is totally lock-free / wait-free though, so it's really not
237 // too shabby, because it never has to deal with a page-table mutex.
238 do {
239 page_attr_packed = fixedobj_pages[page].attr.packed;
240 if (page_attr_packed == 0)
241 if ((page_attr_packed =
242 __sync_val_compare_and_swap(&fixedobj_pages[page].attr.packed,
243 0, attributes)) == 0) {
244 // Atomically assign MAX(old_free_pointer, new_free_pointer)
245 // into the free pointer.
246 free_pointer_sym = SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER);
247 new_free_pointer = (lispobj)low_page_address(page+1);
248 old_free_pointer = free_pointer_sym->value;
249 while (new_free_pointer > old_free_pointer) {
250 actual_old =
251 __sync_val_compare_and_swap(&free_pointer_sym->value,
252 old_free_pointer,
253 new_free_pointer);
254 if (actual_old == old_free_pointer)
255 break;
256 old_free_pointer = actual_old;
258 return page;
260 if (ATTRIBUTES_MATCH_P(page_attr_packed, attributes)
261 && !page_full_p(page)) {
262 // Try to avoid new objects on pages with any pseudo-static objects,
263 // because then touching the young object forces scanning the page,
264 // which is unfortunate if most things on it were untouched.
265 if (fixedobj_pages[page].gens < (1<<PSEUDO_STATIC_GENERATION)) {
266 // instant win
267 return page;
268 } else if (fixedobj_pages[page].gens < best_genmask) {
269 best_genmask = fixedobj_pages[page].gens;
270 best_page = page;
273 if (++page >= FIRST_VARYOBJ_PAGE) page = 0;
274 } while (page != hint_page);
275 if (best_page >= 0)
276 return best_page;
277 lose("No more immobile pages available");
280 // Unused, but possibly will be for some kind of collision-avoidance scheme
281 // on claiming of new free pages.
282 long immobile_alloc_collisions;
284 /* Beginning at page index *hint, attempt to find space
285 for an object on a page with page_attributes. Write its header word
286 and return a C (native) pointer. The start page MUST have the proper
287 characteristisc, but might be totally full.
289 Precondition: Lisp has established a pseudo-atomic section. */
291 /* There is a slightly different algorithm that would probably be faster
292 than what is currently implemented:
293 - hint should be the address of a word that you try to claim
294 as an object header; it moves from high-to-low instead of low-to-high.
295 It's easier to compute the page base than the last valid object start
296 if there are some wasted words at the end due to page size not being
297 a perfect multiple of object size.
298 - you do a CAS into that word, and either suceed or fail
299 - if you succeed, subtract the object spacing and compare
300 to the page's base address, which can be computed by
301 masking. if the next address is above or equal to the page start,
302 store it in the hint, otherwise mark the page full */
304 lispobj alloc_immobile_obj(int page_attributes, lispobj header, int* hint)
306 int page;
307 lispobj word;
308 char * page_data, * obj_ptr, * next_obj_ptr, * limit, * next_free;
309 int spacing_in_bytes = OBJ_SPACING(page_attributes) << WORD_SHIFT;
311 page = *hint;
312 gc_dcheck(low_page_address(page) < (void*)SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value);
313 do {
314 page_data = low_page_address(page);
315 obj_ptr = page_data + fixedobj_pages[page].free_index;
316 limit = page_data + IMMOBILE_CARD_BYTES - spacing_in_bytes;
317 while (obj_ptr <= limit) {
318 word = *(lispobj*)obj_ptr;
319 next_obj_ptr = obj_ptr + spacing_in_bytes;
320 if (fixnump(word) // a fixnum marks free space
321 && __sync_bool_compare_and_swap((lispobj*)obj_ptr,
322 word, header)) {
323 // The value formerly in the header word was the offset to
324 // the next hole. Use it to update the freelist pointer.
325 // Just slam it in.
326 fixedobj_pages[page].free_index = next_obj_ptr + word - page_data;
327 return (lispobj)obj_ptr;
329 // If some other thread updated the free_index
330 // to a larger value, use that. (See example below)
331 next_free = page_data + fixedobj_pages[page].free_index;
332 obj_ptr = next_free > next_obj_ptr ? next_free : next_obj_ptr;
334 set_page_full(page);
335 page = get_freeish_page(page+1 >= FIRST_VARYOBJ_PAGE ? 0 : page+1,
336 page_attributes);
337 *hint = page;
338 } while (1);
342 Example: Conside the freelist initially pointing to word index 6
343 Threads A, and B, and C each want to claim index 6.
344 - Thread A wins and then is switched out immediately after the CAS.
345 - Thread B fails to claim cell 6, claims cell 12 instead.
346 - Thread C fails to claim a cell and is switched out immediately
347 after the CAS.
348 - Thread B writes the index of the next hole, cell 18 into the
349 page's freelist cell.
350 - Thread A wakes up and writes 12 into the freelist cell.
351 - Thread C wakes up sees 12 for next_offset. 12 is greater than 6,
352 so it sets its next probe location to 12.
353 It fails the fixnump(header) test.
354 - Thread C sees that next_offset is still 12,
355 so it skips by the page's object spacing instead, and will continue
356 to do so until hitting the end of the page.
359 //// The collector
361 void update_immobile_nursery_bits()
363 low_page_index_t page;
364 lispobj fixedobj_free_ptr = SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value;
365 lispobj varyobj_free_ptr = SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
367 // Find the high water marks for this GC scavenge phase
368 // [avoid passing exactly IMMOBILE_SPACE_END, which has no page index]
369 max_used_fixedobj_page = find_immobile_page_index((void*)(fixedobj_free_ptr-1));
370 max_used_varyobj_page = find_immobile_page_index((void*)(varyobj_free_ptr-1));
372 immobile_scav_queue = (unsigned int*)low_page_address(max_used_varyobj_page+1);
373 gc_assert((IMMOBILE_SPACE_END - (uword_t)immobile_scav_queue) / sizeof(int)
374 >= QCAPACITY);
376 if (ENABLE_PAGE_PROTECTION) {
377 // Unprotect the in-use ranges. Any page could be written during scavenge
378 os_protect((os_vm_address_t)IMMOBILE_SPACE_START,
379 fixedobj_free_ptr - IMMOBILE_SPACE_START,
380 OS_VM_PROT_ALL);
382 // varyobj_free_ptr is typically not page-aligned - only by random chance
383 // might it be. Additionally we need a page beyond that for the re-scan queue.
384 os_vm_address_t limit = (char*)immobile_scav_queue + IMMOBILE_CARD_BYTES;
385 os_protect((os_vm_address_t)(IMMOBILE_VARYOBJ_SUBSPACE_START),
386 limit - (os_vm_address_t)IMMOBILE_VARYOBJ_SUBSPACE_START,
387 OS_VM_PROT_ALL);
390 for (page=0; page <= max_used_fixedobj_page ; ++page) {
391 // any page whose free index changed contains nursery objects
392 if (fixedobj_pages[page].free_index >> WORD_SHIFT !=
393 fixedobj_pages[page].prior_gc_free_word_index)
394 fixedobj_pages[page].gens |= 1;
395 #ifdef VERIFY_PAGE_GENS
396 check_fixedobj_page(page);
397 #endif
399 #ifdef VERIFY_PAGE_GENS
400 check_varyobj_pages();
401 #endif
404 /* Turn a white object grey. Also enqueue the object for re-scan if required */
405 void
406 promote_immobile_obj(lispobj *ptr, int rescan) // a native pointer
408 if (widetag_of(*ptr) == SIMPLE_FUN_WIDETAG)
409 ptr = fun_code_header(ptr);
410 gc_assert(__immobile_obj_gen_bits(ptr) == from_space);
411 int pointerish = !unboxed_obj_widetag_p(widetag_of(*ptr));
412 assign_generation(ptr, (pointerish ? 0 : IMMOBILE_OBJ_VISITED_FLAG) | new_space);
413 low_page_index_t page_index = find_immobile_page_index(ptr);
415 if (page_index >= FIRST_VARYOBJ_PAGE) {
416 VARYOBJ_PAGE_GENS(page_index) |= 1<<new_space;
417 } else {
418 fixedobj_pages[page_index].gens |= 1<<new_space;
420 // If called from preserve_pointer(), then we haven't scanned immobile
421 // roots yet, so we only need ensure that this object's page's WP bit
422 // is cleared so that the page is not skipped during root scan.
423 if (!rescan) {
424 if (pointerish) {
425 if (page_index >= FIRST_VARYOBJ_PAGE)
426 varyobj_page_touched_bits[(page_index-FIRST_VARYOBJ_PAGE)/32]
427 |= 1 << (page_index & 31);
428 else
429 SET_WP_FLAG(page_index, WRITE_PROTECT_CLEARED);
431 return; // No need to enqueue.
434 // Do nothing if either we don't need to look for pointers in this object,
435 // or the work queue has already overflowed, causing a full scan.
436 if (!pointerish || immobile_scav_queue_count > QCAPACITY) return;
438 // count is either less than or equal to QCAPACITY.
439 // If equal, just bump the count to signify overflow.
440 if (immobile_scav_queue_count < QCAPACITY) {
441 immobile_scav_queue[immobile_scav_queue_head] =
442 (uword_t)ptr & 0xFFFFFFFF; // Drop the high bits
443 immobile_scav_queue_head = (immobile_scav_queue_head + 1) & (QCAPACITY - 1);
445 ++immobile_scav_queue_count;
448 /* If 'addr' points to an immobile object, then make the object
449 live by promotion. But if the object is not in the generation
450 being collected, do nothing */
451 void immobile_space_preserve_pointer(void* addr)
453 low_page_index_t page_index = find_immobile_page_index(addr);
454 if (page_index < 0)
455 return;
457 lispobj* object_start;
458 int promote = 0;
459 if (page_index >= FIRST_VARYOBJ_PAGE) {
460 // Restrict addr to lie below IMMOBILE_SPACE_FREE_POINTER.
461 // This way, if the gens byte is nonzero but there is
462 // a final array acting as filler on the remainder of the
463 // final page, we won't accidentally find that.
464 lispobj* scan_start;
465 promote = (lispobj)addr < SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value
466 && (varyobj_page_gens_augmented(page_index) & (1<<from_space)) != 0
467 && (scan_start = varyobj_scan_start(page_index)) <= (lispobj*)addr
468 && (object_start = gc_search_space(scan_start, addr)) != 0
469 && !immobile_filler_p(object_start)
470 && (instruction_ptr_p(addr, object_start)
471 || properly_tagged_descriptor_p(addr, object_start));
472 } else if (fixedobj_pages[page_index].gens & (1<<from_space)) {
473 int obj_spacing = (page_obj_align(page_index) << WORD_SHIFT);
474 int obj_index = ((uword_t)addr & (IMMOBILE_CARD_BYTES-1)) / obj_spacing;
475 dprintf((logfile,"Pointer %p is to immobile page %d, object %d\n",
476 addr, page_index, obj_index));
477 char* page_start_addr = (char*)((uword_t)addr & ~(IMMOBILE_CARD_BYTES-1));
478 object_start = (lispobj*)(page_start_addr + obj_index * obj_spacing);
479 promote = !fixnump(*object_start)
480 && (lispobj*)addr < object_start + page_obj_size(page_index)
481 && properly_tagged_descriptor_p(addr, object_start);
483 if (promote && __immobile_obj_gen_bits(object_start) == from_space) {
484 dprintf((logfile,"immobile obj @ %p (<- %p) is conservatively live\n",
485 header_addr, addr));
486 promote_immobile_obj(object_start, 0);
490 // Loop over the newly-live objects, scavenging them for pointers.
491 // As with the ordinary gencgc algorithm, this uses almost no stack.
492 static void full_scavenge_immobile_newspace()
494 page_index_t page;
495 unsigned char bit = 1<<new_space;
497 // Fixed-size object pages.
499 for (page = 0; page <= max_used_fixedobj_page; ++page) {
500 if (!(fixedobj_pages[page].gens & bit)) continue;
501 // Skip amount within the loop is in bytes.
502 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
503 lispobj* obj = low_page_address(page);
504 // Use an inclusive, not exclusive, limit. On pages with dense packing
505 // (i.e. non-LAYOUT), if the object size does not evenly divide the page
506 // size, it is wrong to examine memory at an address which could be
507 // an object start, but for the fact that it runs off the page boundary.
508 // On the other hand, unused words hold 0, so it's kind of ok to read them.
509 lispobj* limit = (lispobj*)((char*)obj +
510 IMMOBILE_CARD_BYTES - obj_spacing);
511 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
512 if (!fixnump(*obj) && __immobile_obj_gen_bits(obj) == new_space) {
513 set_visited(obj);
514 lispobj header = *obj;
515 scavtab[widetag_of(header)](obj, header);
520 // Variable-size object pages
522 page = FIRST_VARYOBJ_PAGE - 1; // Subtract 1 because of pre-increment
523 while (1) {
524 // Find the next page with anything in newspace.
525 do {
526 if (++page > max_used_varyobj_page) return;
527 } while ((VARYOBJ_PAGE_GENS(page) & bit) == 0);
528 lispobj* obj = varyobj_scan_start(page);
529 do {
530 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
531 int n_words;
532 for ( ; obj < limit ; obj += n_words ) {
533 lispobj header = *obj;
534 if (__immobile_obj_gen_bits(obj) == new_space) {
535 set_visited(obj);
536 n_words = scavtab[widetag_of(header)](obj, header);
537 } else {
538 n_words = sizetab[widetag_of(header)](obj);
541 page = find_immobile_page_index(obj);
542 // Bail out if exact absolute end of immobile space was reached.
543 if (page < 0) return;
544 // If 'page' should be scanned, then pick up where we left off,
545 // without recomputing 'obj' but setting a higher 'limit'.
546 } while (VARYOBJ_PAGE_GENS(page) & bit);
550 /// Repeatedly scavenge immobile newspace work queue until we find no more
551 /// reachable objects within. (They might be in dynamic space though).
552 /// If queue overflow already happened, then a worst-case full scan is needed.
553 /// If it didn't, we try to drain the queue, hoping that overflow does
554 /// not happen while doing so.
555 /// The approach taken is more subtle than just dequeuing each item,
556 /// scavenging, and letting the outer 'while' loop take over.
557 /// That would be ok, but could cause more full scans than necessary.
558 /// Instead, since each entry in the queue is useful information
559 /// in the non-overflow condition, perform all the work indicated thereby,
560 /// rather than considering the queue discardable as soon as overflow happens.
561 /// Essentially we just have to capture the valid span of enqueued items,
562 /// because the queue state is inconsistent when 'count' exceeds 'capacity'.
563 void scavenge_immobile_newspace()
565 while (immobile_scav_queue_count) {
566 if (immobile_scav_queue_count > QCAPACITY) {
567 immobile_scav_queue_count = 0;
568 full_scavenge_immobile_newspace();
569 } else {
570 int queue_index_from = (immobile_scav_queue_head - immobile_scav_queue_count)
571 & (QCAPACITY - 1);
572 int queue_index_to = immobile_scav_queue_head;
573 int i = queue_index_from;
574 // The termination condition can't be expressed as an inequality,
575 // since the indices might be reversed due to wraparound.
576 // To express as equality entails forcing at least one iteration
577 // since the ending index might be the starting index.
578 do {
579 lispobj* obj = (lispobj*)(uword_t)immobile_scav_queue[i];
580 i = (1 + i) & (QCAPACITY-1);
581 // Only decrement the count if overflow did not happen.
582 // The first iteration of this loop will decrement for sure,
583 // but subsequent iterations might not.
584 if (immobile_scav_queue_count <= QCAPACITY)
585 --immobile_scav_queue_count;
586 if (!(__immobile_obj_gen_bits(obj) & IMMOBILE_OBJ_VISITED_FLAG)) {
587 set_visited(obj);
588 lispobj header = *obj;
589 scavtab[widetag_of(header)](obj, header);
591 } while (i != queue_index_to);
596 // Return a page >= page_index having potential old->young pointers,
597 // or -1 if there isn't one.
598 static int next_varyobj_root_page(unsigned int page_index,
599 unsigned int end_bitmap_index,
600 unsigned char genmask)
602 unsigned int map_index = (page_index - FIRST_VARYOBJ_PAGE) / 32;
603 if (map_index >= end_bitmap_index) return -1;
604 int bit_index = page_index & 31;
605 // Look only at bits of equal or greater weight than bit_index.
606 unsigned int word = (0xFFFFFFFFU << bit_index) & varyobj_page_touched_bits[map_index];
607 while (1) {
608 if (word) {
609 bit_index = ffs(word) - 1;
610 page_index = FIRST_VARYOBJ_PAGE + map_index * 32 + bit_index;
611 if (varyobj_page_gens_augmented(page_index) & genmask)
612 return page_index;
613 else {
614 word ^= (1<<bit_index);
615 continue;
618 if (++map_index >= end_bitmap_index) return -1;
619 word = varyobj_page_touched_bits[map_index];
623 void
624 scavenge_immobile_roots(generation_index_t min_gen, generation_index_t max_gen)
626 // example: scavenging gens 2..6, the mask of root gens is #b1111100
627 int genmask = ((1 << (max_gen - min_gen + 1)) - 1) << min_gen;
629 low_page_index_t page;
630 for (page = 0; page <= max_used_fixedobj_page ; ++page) {
631 if (fixedobj_page_wp(page) || !(fixedobj_pages[page].gens & genmask))
632 continue;
633 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
634 lispobj* obj = low_page_address(page);
635 lispobj* limit = (lispobj*)((char*)obj +
636 IMMOBILE_CARD_BYTES - obj_spacing);
637 int gen;
638 // Immobile space can only contain objects with a header word,
639 // no conses, so any fixnum where a header could be is not a live
640 // object.
641 do {
642 if (!fixnump(*obj) && (genmask >> (gen=__immobile_obj_gen_bits(obj)) & 1)) {
643 if (gen == new_space) { set_visited(obj); }
644 lispobj header = *obj;
645 scavtab[widetag_of(header)](obj, header);
647 } while ((obj = (lispobj*)((char*)obj + obj_spacing)) <= limit);
650 // Variable-length object pages
651 unsigned n_varyobj_pages = 1+max_used_varyobj_page-FIRST_VARYOBJ_PAGE;
652 unsigned end_bitmap_index = (n_varyobj_pages+31)/32;
653 page = next_varyobj_root_page(FIRST_VARYOBJ_PAGE, end_bitmap_index, genmask);
654 while (page >= 0) {
655 lispobj* obj = varyobj_scan_start(page);
656 do {
657 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
658 int n_words, gen;
659 for ( ; obj < limit ; obj += n_words ) {
660 lispobj header = *obj;
661 if (genmask >> (gen=__immobile_obj_gen_bits(obj)) & 1) {
662 if (gen == new_space) { set_visited(obj); }
663 n_words = scavtab[widetag_of(header)](obj, header);
664 } else {
665 n_words = sizetab[widetag_of(header)](obj);
668 page = find_immobile_page_index(obj);
669 } while (page > 0
670 && (VARYOBJ_PAGE_GENS(page) & genmask)
671 && varyobj_page_touched(page));
672 page = next_varyobj_root_page(1+page, end_bitmap_index, genmask);
674 scavenge_immobile_newspace();
677 #include "genesis/layout.h"
678 #define LAYOUT_SIZE (sizeof (struct layout)/N_WORD_BYTES)
679 #define LAYOUT_ALIGN 256 /*bytes*/
680 #define LAYOUT_OF_LAYOUT ((IMMOBILE_SPACE_START+2*LAYOUT_ALIGN)|INSTANCE_POINTER_LOWTAG)
681 #define LAYOUT_OF_PACKAGE ((IMMOBILE_SPACE_START+8*LAYOUT_ALIGN)|INSTANCE_POINTER_LOWTAG)
683 // As long as Lisp doesn't have any native allocators (vops and whatnot)
684 // it doesn't need to access these values.
685 int layout_page_hint, symbol_page_hint, fdefn_page_hint;
687 // For the three different page characteristics that we need,
688 // claim a page that works for those characteristics.
689 void set_immobile_space_hints()
691 // The allocator doesn't check whether each 'hint' points to an
692 // expected kind of page, so we have to ensure up front that
693 // allocations start on different pages. i.e. You can point to
694 // a totally full page, but you can't point to a wrong page.
695 // It doesn't work to just assign these to consecutive integers
696 // without also updating the page attributes.
698 // Object sizes must be multiples of 2 because the n_words value we pass
699 // to scavenge() is gotten from the page attributes, and scavenge asserts
700 // that the ending address is aligned to a doubleword boundary as expected.
702 // LAYOUTs are 256-byte-aligned so that the low byte contains no information.
703 // This makes it possible to recover a layout pointer from an instance header
704 // by simply changing the low byte to instance-pointer-lowtag.
705 // As a test of objects using larger-than-required alignment,
706 // the 64-bit implementation uses 256-byte alignment for layouts,
707 // even though the header can store all bits of the layout pointer.
708 // The 32-bit implementation would also need somewhere different to store
709 // the generation byte of each layout, which is a minor annoyance.
710 layout_page_hint = get_freeish_page(0, MAKE_ATTR(LAYOUT_ALIGN / N_WORD_BYTES, // spacing
711 CEILING(LAYOUT_SIZE,2),
712 0));
713 symbol_page_hint = get_freeish_page(0, MAKE_ATTR(CEILING(SYMBOL_SIZE,2),
714 CEILING(SYMBOL_SIZE,2),
715 0));
716 fdefn_page_hint = get_freeish_page(0, MAKE_ATTR(CEILING(FDEFN_SIZE,2),
717 CEILING(FDEFN_SIZE,2),
718 0));
721 void write_protect_immobile_space()
723 immobile_scav_queue = NULL;
724 immobile_scav_queue_head = 0;
726 set_immobile_space_hints();
728 if (!ENABLE_PAGE_PROTECTION)
729 return;
731 // Now find contiguous ranges of pages that are protectable,
732 // minimizing the number of system calls as much as possible.
733 int i, start = -1, end = -1; // inclusive bounds on page indices
734 for (i = max_used_fixedobj_page ; i >= 0 ; --i) {
735 if (fixedobj_page_wp(i)) {
736 if (end < 0) end = i;
737 start = i;
739 if (end >= 0 && (!fixedobj_page_wp(i) || i == 0)) {
740 os_protect(low_page_address(start),
741 IMMOBILE_CARD_BYTES * (1 + end - start),
742 OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
743 start = end = -1;
746 #define varyobj_page_wp(x) !varyobj_page_touched(x)
747 for (i = max_used_varyobj_page ; i >= FIRST_VARYOBJ_PAGE ; --i) {
748 if (varyobj_page_wp(i)) {
749 if (end < 0) end = i;
750 start = i;
752 if (end >= 0 && (!varyobj_page_wp(i) || i == FIRST_VARYOBJ_PAGE)) {
753 os_protect(low_page_address(start),
754 IMMOBILE_CARD_BYTES * (1 + end - start),
755 OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
756 start = end = -1;
759 #undef varyobj_page_wp
762 // Scan range between start and end (exclusive) for old-to-young pointers.
763 // 'keep_gen' is the value of the generation byte of objects that were
764 // candidates to become garbage, but remain live after this gc.
765 // It will necessarily have the VISITED flag on.
766 // 'new_gen' is the generation number that those objects will have
767 // after collection, which is either the same generation or one higher,
768 // depending on the 'raise' flag for this GC cycle.
769 static int
770 range_points_to_younger_p(lispobj* obj, lispobj* end,
771 int gen, int keep_gen, int new_gen)
773 #ifdef DEBUG
774 lispobj* __attribute__((unused)) saved_obj = obj, __attribute__((unused)) header = *obj;
775 #endif
776 do {
777 lispobj thing = *obj;
778 if (is_lisp_pointer(thing)) {
779 int to_page = find_page_index((void*)thing),
780 to_gen = 255;
781 if (to_page >= 0) { // points to ordinary dynamic space
782 to_gen = page_table[to_page].gen;
783 if (to_gen == PSEUDO_STATIC_GENERATION+1) // scratch gen
784 to_gen = new_gen; // is actually this
785 } else if (immobile_space_p(thing)) {
786 // Processing the code-entry-points slot of a code component
787 // requires the general variant of immobile_obj_gen_bits
788 // because the pointed-to object is a simple-fun.
789 to_gen = immobile_obj_gen_bits(native_pointer(thing));
790 if (to_gen == keep_gen) // keep gen
791 to_gen = new_gen; // is actually this
793 if (to_gen < gen) {
794 return 1; // yes, points to younger
797 } while (++obj < end);
798 return 0; // no, does not point to younger
801 // Scan a fixed-size object for old-to-young pointers.
802 // Since fixed-size objects are boxed and on known boundaries,
803 // we never start in the middle of random bytes, so the answer is exact.
804 static inline boolean
805 fixedobj_points_to_younger_p(lispobj* obj, int n_words,
806 int gen, int keep_gen, int new_gen)
808 unsigned char widetag = widetag_of(*obj);
809 lispobj __attribute__((unused)) funobj[1], layout[1];
810 lispobj lbitmap;
812 switch (widetag) {
813 #ifdef LISP_FEATURE_IMMOBILE_CODE
814 case FDEFN_WIDETAG:
815 funobj[0] = fdefn_raw_referent((struct fdefn*)obj);
816 return range_points_to_younger_p(funobj, funobj+1, gen, keep_gen, new_gen)
817 || range_points_to_younger_p(obj+1, obj+3, gen, keep_gen, new_gen);
818 #endif
819 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
820 case INSTANCE_WIDETAG:
821 case FUNCALLABLE_INSTANCE_WIDETAG:
822 layout[0] = instance_layout(obj);
823 if (range_points_to_younger_p(layout, layout+1, gen, keep_gen, new_gen))
824 return 1;
825 lbitmap = ((struct layout*)native_pointer(layout[0]))->bitmap;
826 if (lbitmap != make_fixnum(-1)) {
827 gc_assert(fixnump(lbitmap)); // No bignums (yet)
828 sword_t bitmap = (sword_t)lbitmap >> N_FIXNUM_TAG_BITS;
829 lispobj* where = obj + 1;
830 for ( ; --n_words ; ++where, bitmap >>= 1 )
831 if ((bitmap & 1) != 0 &&
832 range_points_to_younger_p(where, where+1, gen, keep_gen, new_gen))
833 return 1;
834 return 0;
836 // FALLTHROUGH_INTENDED
837 #endif
839 return range_points_to_younger_p(obj+1, obj+n_words, gen, keep_gen, new_gen);
842 static boolean
843 varyobj_points_to_younger_p(lispobj* obj, int gen, int keep_gen, int new_gen,
844 os_vm_address_t page_begin,
845 os_vm_address_t page_end) // upper (exclusive) bound
847 lispobj *begin, *end, word = *obj;
848 unsigned char widetag = widetag_of(word);
849 if (widetag == CODE_HEADER_WIDETAG) { // usual case. Like scav_code_header()
850 for_each_simple_fun(i, function_ptr, (struct code*)obj, 0, {
851 begin = SIMPLE_FUN_SCAV_START(function_ptr);
852 end = begin + SIMPLE_FUN_SCAV_NWORDS(function_ptr);
853 if (page_begin > (os_vm_address_t)begin) begin = (lispobj*)page_begin;
854 if (page_end < (os_vm_address_t)end) end = (lispobj*)page_end;
855 if (end > begin
856 && range_points_to_younger_p(begin, end, gen, keep_gen, new_gen))
857 return 1;
859 begin = obj + 1; // skip the header
860 end = obj + code_header_words(word); // exclusive bound on boxed slots
861 } else if (widetag == SIMPLE_VECTOR_WIDETAG) {
862 sword_t length = fixnum_value(((struct vector *)obj)->length);
863 begin = obj + 2; // skip the header and length
864 end = obj + CEILING(length + 2, 2);
865 } else if (unboxed_obj_widetag_p(widetag)) {
866 return 0;
867 } else {
868 lose("Unexpected widetag @ %p", obj);
870 // Fallthrough: scan words from begin to end
871 if (page_begin > (os_vm_address_t)begin) begin = (lispobj*)page_begin;
872 if (page_end < (os_vm_address_t)end) end = (lispobj*)page_end;
873 if (end > begin && range_points_to_younger_p(begin, end, gen, keep_gen, new_gen))
874 return 1;
875 return 0;
878 /// The next two functions are analogous to 'update_page_write_prot()'
879 /// but they differ in that they are "precise" - random code bytes that look
880 /// like pointers are not accidentally treated as pointers.
882 // If 'page' does not contain any objects that points to an object
883 // younger than themselves, then return true.
884 // This is called on pages that do not themselves contain objects of
885 // the generation being collected, but might contain pointers
886 // to younger generations, which we detect by a cleared WP status bit.
887 // The bit is cleared on any write, though, even of a non-pointer,
888 // so this unfortunately has to be tested much more often than we'd like.
889 static inline boolean can_wp_fixedobj_page(page_index_t page, int keep_gen, int new_gen)
891 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
892 int obj_size_words = page_obj_size(page);
893 lispobj* obj = low_page_address(page);
894 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES - obj_spacing);
895 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) )
896 if (!fixnump(*obj) && // an object header
897 fixedobj_points_to_younger_p(obj, obj_size_words,
898 __immobile_obj_generation(obj),
899 keep_gen, new_gen))
900 return 0;
901 return 1;
904 // To scan _only_ 'page' is impossible in general, but we can act like only
905 // one page was scanned by backing up to the first object whose end is on
906 // or after it, and then restricting points_to_younger within the boundaries.
907 // Doing it this way is probably much better than conservatively assuming
908 // that any word satisfying is_lisp_pointer() is a pointer.
909 static inline boolean can_wp_varyobj_page(page_index_t page, int keep_gen, int new_gen)
911 lispobj *begin = (lispobj*)low_page_address(page);
912 lispobj *end = begin + WORDS_PER_PAGE;
913 lispobj *obj = varyobj_scan_start(page);
914 for ( ; obj < end ; obj += sizetab[widetag_of(*obj)](obj) ) {
915 gc_assert(other_immediate_lowtag_p(*obj));
916 if (!immobile_filler_p(obj) &&
917 varyobj_points_to_younger_p(obj,
918 __immobile_obj_generation(obj),
919 keep_gen, new_gen,
920 (os_vm_address_t)begin,
921 (os_vm_address_t)end))
922 return 0;
924 return 1;
928 Sweep immobile space by zeroing the memory of trashed objects
929 and linking them into the freelist.
931 Possible improvements:
932 - If an entire page becomes nothing but holes, we could bzero it
933 instead of object-at-a-time clearing. But it's not known to be
934 so until after the sweep, so it would entail two passes per page,
935 one to mark holes and one to zero them.
936 - And perhaps bzero could be used on ranges of holes, because
937 in that case each hole's pointer to the next hole is zero as well.
940 #define SETUP_GENS() \
941 /* Only care about pages with something in old or new space. */ \
942 int relevant_genmask = (1 << from_space) | (1 << new_space); \
943 /* Objects whose gen byte is 'keep_gen' are alive. */ \
944 int keep_gen = IMMOBILE_OBJ_VISITED_FLAG | new_space; \
945 /* Objects whose gen byte is 'from_space' are trash. */ \
946 int discard_gen = from_space; \
947 /* Moving non-garbage into either 'from_space' or 'from_space+1' */ \
948 generation_index_t new_gen = from_space + (raise!=0)
950 // The new value of the page generation mask is computed as follows:
951 // If 'raise' = 1 then:
952 // Nothing resides in 'from_space', and 'from_space+1' gains new objects
953 // if and only if any objects on the page were retained.
954 // If 'raise' = 0 then:
955 // Nothing resides in the scratch generation, and 'from_space'
956 // has objects if and only if any objects were retained.
957 #define COMPUTE_NEW_MASK(var, old) \
958 int var = old & ~(1<<from_space); \
959 if ( raise ) \
960 var |= 1<<(from_space+1) & any_kept; \
961 else \
962 var = (var & ~(1<<new_space)) | (1<<from_space & any_kept)
964 static void
965 sweep_fixedobj_pages(int raise)
967 char *page_base;
968 lispobj *obj, *limit, *hole;
969 // This will be needed for space accounting.
970 // threads might fail to consume all the space on a page.
971 // By storing in the page table the count of holes that really existed
972 // at the start of the prior GC, and subtracting from that the number
973 // that exist now, we know how much usable space was obtained (per page).
974 int n_holes = 0;
975 int word_idx;
977 SETUP_GENS();
979 low_page_index_t page;
980 for (page = 0; page <= max_used_fixedobj_page; ++page) {
981 // On pages that won't need manipulation of the freelist,
982 // we try to do less work than for pages that need it.
983 if (!(fixedobj_pages[page].gens & relevant_genmask)) {
984 // Scan for old->young pointers, and WP if there are none.
985 if (ENABLE_PAGE_PROTECTION && !fixedobj_page_wp(page)
986 && fixedobj_pages[page].gens > 1
987 && can_wp_fixedobj_page(page, keep_gen, new_gen))
988 SET_WP_FLAG(page, WRITE_PROTECT);
989 continue;
991 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
992 int obj_size_words = page_obj_size(page);
993 page_base = low_page_address(page);
994 limit = (lispobj*)(page_base + IMMOBILE_CARD_BYTES - obj_spacing);
995 obj = (lispobj*)page_base;
996 hole = NULL;
997 int any_kept = 0; // was anything moved to the kept generation
998 n_holes = 0;
1000 // wp_it is 1 if we should try to write-protect it now.
1001 // If already write-protected, skip the tests.
1002 int wp_it = ENABLE_PAGE_PROTECTION && !fixedobj_page_wp(page);
1003 int gen;
1004 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1005 if (fixnump(*obj)) { // was already a hole
1006 trash_it:
1007 // re-link it into the new freelist
1008 if (hole)
1009 // store the displacement from the end of the object
1010 // at prev_hole to the start of this object.
1011 *hole = (lispobj)((char*)obj - ((char*)hole + obj_spacing));
1012 else // this is the first seen hole on the page
1013 // record the byte offset to that hole
1014 fixedobj_pages[page].free_index = (char*)obj - page_base;
1015 hole = obj;
1016 n_holes ++;
1017 } else if ((gen = __immobile_obj_gen_bits(obj)) == discard_gen) { // trash
1018 for (word_idx=obj_size_words-1 ; word_idx > 0 ; --word_idx)
1019 obj[word_idx] = 0;
1020 goto trash_it;
1021 } else if (gen == keep_gen) {
1022 assign_generation(obj, gen = new_gen);
1023 #ifdef DEBUG
1024 gc_assert(!fixedobj_points_to_younger_p(obj, obj_size_words,
1025 gen, keep_gen, new_gen));
1026 #endif
1027 any_kept = -1;
1028 } else if (wp_it && fixedobj_points_to_younger_p(obj, obj_size_words,
1029 gen, keep_gen, new_gen))
1030 wp_it = 0;
1032 if ( hole ) // terminate the chain of holes
1033 *hole = (lispobj)((char*)obj - ((char*)hole + obj_spacing));
1034 fixedobj_pages[page].prior_gc_free_word_index =
1035 fixedobj_pages[page].free_index >> WORD_SHIFT;
1037 COMPUTE_NEW_MASK(mask, fixedobj_pages[page].gens);
1038 if ( mask ) {
1039 fixedobj_pages[page].gens = mask;
1040 if (wp_it) {
1041 SET_WP_FLAG(page, WRITE_PROTECT);
1042 dprintf((logfile, "Lowspace: set WP on page %d\n", page));
1044 } else {
1045 dprintf((logfile,"page %d is all garbage\n", page));
1046 fixedobj_pages[page].attr.packed = 0;
1048 #ifdef DEBUG
1049 check_fixedobj_page(page);
1050 #endif
1051 dprintf((logfile,"page %d: %d holes\n", page, n_holes));
1055 void verify_immobile_page_protection(int,int);
1057 // Scan for freshly trashed objects and turn them into filler.
1058 // Lisp is responsible for consuming the free space
1059 // when it next allocates a variable-size object.
1060 static void
1061 sweep_varyobj_pages(int raise)
1063 SETUP_GENS();
1065 lispobj* free_pointer = (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
1066 low_page_index_t page;
1067 for (page = FIRST_VARYOBJ_PAGE; page <= max_used_varyobj_page; ++page) {
1068 int genmask = VARYOBJ_PAGE_GENS(page);
1069 if (!(genmask & relevant_genmask)) { // Has nothing in oldspace or newspace.
1070 // Scan for old->young pointers, and WP if there are none.
1071 if (ENABLE_PAGE_PROTECTION && varyobj_page_touched(page)
1072 && varyobj_page_gens_augmented(page) > 1
1073 && can_wp_varyobj_page(page, keep_gen, new_gen))
1074 varyobj_page_touched_bits[(page - FIRST_VARYOBJ_PAGE)/32] &= ~(1<<(page & 31));
1075 continue;
1077 lispobj* page_base = (lispobj*)low_page_address(page);
1078 lispobj* limit = page_base + WORDS_PER_PAGE;
1079 if (limit > free_pointer) limit = free_pointer;
1080 int any_kept = 0; // was anything moved to the kept generation
1081 // wp_it is 1 if we should try to write-protect it now.
1082 // If already write-protected, skip the tests.
1083 int wp_it = ENABLE_PAGE_PROTECTION && varyobj_page_touched(page);
1084 lispobj* obj = varyobj_scan_start(page);
1085 int size, gen;
1087 if (obj < page_base) {
1088 // An object whose tail is on this page, or which spans this page,
1089 // would have been promoted/kept while dealing with the page with
1090 // the object header. Therefore we don't need to consider that object,
1091 // * except * that we do need to consider whether it is an old object
1092 // pointing to a young object.
1093 if (wp_it // If we wanted to try write-protecting this page,
1094 // and the object starting before this page is strictly older
1095 // than the generation that we're moving retained objects into
1096 && (gen = __immobile_obj_gen_bits(obj)) > new_gen
1097 // and it contains an old->young pointer
1098 && varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1099 (os_vm_address_t)page_base,
1100 (os_vm_address_t)limit)) {
1101 wp_it = 0;
1103 // We MUST skip this object in the sweep, because in the case of
1104 // non-promotion (raise=0), we could see an object in from_space
1105 // and believe it to be dead.
1106 obj += sizetab[widetag_of(*obj)](obj);
1107 // obj can't hop over this page. If it did, there would be no
1108 // headers on the page, and genmask would have been zero.
1109 gc_assert(obj < limit);
1111 for ( ; obj < limit ; obj += size ) {
1112 lispobj word = *obj;
1113 size = sizetab[widetag_of(word)](obj);
1114 if (immobile_filler_p(obj)) { // do nothing
1115 } else if ((gen = __immobile_obj_gen_bits(obj)) == discard_gen) {
1116 if (size < 4)
1117 lose("immobile object @ %p too small to free", obj);
1118 else { // Create a filler object.
1119 struct code* code = (struct code*)obj;
1120 code->header = 2<<N_WIDETAG_BITS | CODE_HEADER_WIDETAG;
1121 code->code_size = make_fixnum((size - 2) * N_WORD_BYTES);
1122 code->debug_info = varyobj_holes;
1123 varyobj_holes = (lispobj)code;
1125 } else if (gen == keep_gen) {
1126 assign_generation(obj, gen = new_gen);
1127 #ifdef DEBUG
1128 gc_assert(!varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1129 (os_vm_address_t)page_base,
1130 (os_vm_address_t)limit));
1131 #endif
1132 any_kept = -1;
1133 } else if (wp_it &&
1134 varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1135 (os_vm_address_t)page_base,
1136 (os_vm_address_t)limit))
1137 wp_it = 0;
1139 COMPUTE_NEW_MASK(mask, VARYOBJ_PAGE_GENS(page));
1140 VARYOBJ_PAGE_GENS(page) = mask;
1141 if ( mask && wp_it )
1142 varyobj_page_touched_bits[(page - FIRST_VARYOBJ_PAGE)/32] &= ~(1 << (page & 31));
1144 #ifdef DEBUG
1145 verify_immobile_page_protection(keep_gen, new_gen);
1146 #endif
1149 static void compute_immobile_space_bound()
1151 int max;
1152 // find the highest page in use
1153 for (max = FIRST_VARYOBJ_PAGE-1 ; max >= 0 ; --max)
1154 if (fixedobj_pages[max].attr.parts.obj_size)
1155 break;
1156 max_used_fixedobj_page = max; // this is a page index, not the number of pages.
1157 SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value =
1158 IMMOBILE_SPACE_START + IMMOBILE_CARD_BYTES*(1+max);
1160 for (max = (IMMOBILE_SPACE_SIZE/IMMOBILE_CARD_BYTES)-1 ;
1161 max >= FIRST_VARYOBJ_PAGE ; --max)
1162 if (varyobj_page_gens_augmented(max))
1163 break;
1164 max_used_varyobj_page = max; // this is a page index, not the number of pages.
1167 // TODO: (Maybe this won't work. Not sure yet.) rather than use the
1168 // same 'raise' concept as in gencgc, each immobile object can store bits
1169 // indicating whether it has survived any GC at its current generation.
1170 // If it has, then it gets promoted next time, rather than all or nothing
1171 // being promoted from the generation getting collected.
1172 void
1173 sweep_immobile_space(int raise)
1175 gc_assert(immobile_scav_queue_count == 0);
1176 sweep_fixedobj_pages(raise);
1177 sweep_varyobj_pages(raise);
1178 compute_immobile_space_bound();
1181 void gc_init_immobile()
1183 #ifdef DEBUG
1184 logfile = stderr;
1185 #endif
1186 int n_fixedobj_pages = FIRST_VARYOBJ_PAGE;
1187 int n_varyobj_pages = (IMMOBILE_SPACE_SIZE - IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE)
1188 / IMMOBILE_CARD_BYTES;
1189 fixedobj_pages = calloc(n_fixedobj_pages, sizeof(struct fixedobj_page));
1190 gc_assert(fixedobj_pages);
1192 n_bitmap_elts = (n_varyobj_pages + 31) / 32;
1193 int request = n_bitmap_elts * sizeof (int)
1194 + n_varyobj_pages * (sizeof (short)+sizeof (char));
1195 char* varyobj_page_tables = calloc(1, request);
1196 gc_assert(varyobj_page_tables);
1197 varyobj_page_touched_bits = (unsigned int*)varyobj_page_tables;
1198 // The conservative value for 'touched' is 1.
1199 memset(varyobj_page_touched_bits, 0xff, n_bitmap_elts * sizeof (int));
1200 varyobj_page_scan_start_offset = (unsigned short*)(varyobj_page_touched_bits + n_bitmap_elts);
1201 varyobj_page_header_gens = (unsigned char*)(varyobj_page_scan_start_offset + n_varyobj_pages);
1204 /* Because the immobile page table is not dumped into a core image,
1205 we have to reverse-engineer the characteristics of each page,
1206 which means figuring out what the object spacing should be.
1207 This is not difficult, but is a bit of a kludge */
1209 static inline int immobile_obj_spacing(lispobj header_word, lispobj *obj,
1210 int actual_size)
1212 if (widetag_of(header_word) == INSTANCE_WIDETAG &&
1213 instance_layout(obj) == LAYOUT_OF_LAYOUT)
1214 return LAYOUT_ALIGN / N_WORD_BYTES;
1215 else
1216 return actual_size; // in words
1219 // Set the characteristics of each used page at image startup time.
1220 void immobile_space_coreparse(uword_t address, uword_t len)
1222 int n_pages, word_idx, page;
1224 n_pages = (len + IMMOBILE_CARD_BYTES - 1) / IMMOBILE_CARD_BYTES;
1225 if (address == IMMOBILE_SPACE_START) {
1226 for (page = 0 ; page < n_pages ; ++page) {
1227 lispobj* page_data = low_page_address(page);
1228 for (word_idx = 0 ; word_idx < WORDS_PER_PAGE ; ++word_idx) {
1229 lispobj* obj = page_data + word_idx;
1230 lispobj header = *obj;
1231 if (!fixnump(header)) {
1232 gc_assert(other_immediate_lowtag_p(*obj));
1233 int size = sizetab[widetag_of(header)](obj);
1234 fixedobj_pages[page].attr.parts.obj_size = size;
1235 fixedobj_pages[page].attr.parts.obj_align
1236 = immobile_obj_spacing(header, obj, size);
1237 fixedobj_pages[page].gens |= 1 << __immobile_obj_gen_bits(obj);
1238 if (ENABLE_PAGE_PROTECTION)
1239 fixedobj_pages[page].attr.parts.flags = WRITE_PROTECT;
1240 break;
1244 } else if (address == IMMOBILE_VARYOBJ_SUBSPACE_START) {
1245 lispobj* obj = (lispobj*)address;
1246 lispobj* limit = (lispobj*)(address + len);
1247 int n_words;
1248 low_page_index_t last_page = 0;
1249 for ( ; obj < limit ; obj += n_words ) {
1250 n_words = sizetab[widetag_of(*obj)](obj);
1251 if (obj[1] == 0 && (obj[0] == INSTANCE_WIDETAG ||
1252 obj[0] == 0)) {
1253 if (obj[0]) {
1254 // Round up to the next immobile page.
1255 lispobj page_end = CEILING((lispobj)obj, IMMOBILE_CARD_BYTES);
1256 n_words = (lispobj*)page_end - obj;
1257 obj[0] = SIMPLE_ARRAY_FIXNUM_WIDETAG;
1258 obj[1] = make_fixnum(n_words - 2);
1259 } else {
1260 // There are trailing zeros to fill the core file page.
1261 // This happens when the next object is exactly aligned
1262 // to an immobile page. There is no padding object.
1263 gc_assert(((lispobj)obj & (IMMOBILE_CARD_BYTES-1)) == 0);
1265 limit = obj;
1266 break;
1268 if (immobile_filler_p(obj)) {
1269 // Holes were chained through the debug_info slot at save.
1270 // Just update the head of the chain.
1271 varyobj_holes = (lispobj)obj;
1272 continue;
1274 low_page_index_t first_page = find_immobile_page_index(obj);
1275 last_page = find_immobile_page_index(obj+n_words-1);
1276 // Only the page with this object header gets a bit in its gen mask.
1277 VARYOBJ_PAGE_GENS(first_page) |= 1<<__immobile_obj_gen_bits(obj);
1278 // For each page touched by this object, set the page's
1279 // scan_start_offset, unless it was already set.
1280 int page;
1281 for (page = first_page ; page <= last_page ; ++page) {
1282 if (!varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE]) {
1283 long offset = (char*)low_page_address(page+1) - (char*)obj;
1284 varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE]
1285 = offset >> (WORD_SHIFT + 1);
1289 // Write-protect the pages occupied by the core file.
1290 // (There can be no inter-generation pointers.)
1291 if (ENABLE_PAGE_PROTECTION) {
1292 int page;
1293 for (page = FIRST_VARYOBJ_PAGE ; page <= last_page ; ++page)
1294 varyobj_page_touched_bits[(page-FIRST_VARYOBJ_PAGE)/32] &= ~(1<<(page & 31));
1296 SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value = (lispobj)limit;
1297 compute_immobile_space_bound();
1298 } else {
1299 lose("unknown immobile subspace");
1303 // Demote pseudo-static to highest normal generation
1304 // so that all objects become eligible for collection.
1305 void prepare_immobile_space_for_final_gc()
1307 int page;
1308 char* page_base;
1309 char* page_end = (char*)SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value;
1311 // The list of holes need not be saved.
1312 SYMBOL(IMMOBILE_FREELIST)->value = NIL;
1314 for (page_base = (char*)IMMOBILE_SPACE_START, page = 0 ;
1315 page_base < page_end ;
1316 page_base += IMMOBILE_CARD_BYTES, ++page) {
1317 unsigned char mask = fixedobj_pages[page].gens;
1318 if (mask & 1<<PSEUDO_STATIC_GENERATION) {
1319 int obj_spacing = page_obj_align(page) << WORD_SHIFT;
1320 lispobj* obj = (lispobj*)page_base;
1321 lispobj* limit = (lispobj*)(page_base + IMMOBILE_CARD_BYTES - obj_spacing);
1322 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1323 if (!fixnump(*obj)
1324 && __immobile_obj_gen_bits(obj) == PSEUDO_STATIC_GENERATION)
1325 assign_generation(obj, HIGHEST_NORMAL_GENERATION);
1327 fixedobj_pages[page].gens = (mask & ~(1<<PSEUDO_STATIC_GENERATION))
1328 | 1<<HIGHEST_NORMAL_GENERATION;
1332 lispobj* obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1333 lispobj* limit = (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
1334 for ( ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
1335 if (__immobile_obj_gen_bits(obj) == PSEUDO_STATIC_GENERATION)
1336 assign_generation(obj, HIGHEST_NORMAL_GENERATION);
1338 int max_page = find_immobile_page_index(limit-1);
1339 for ( page = FIRST_VARYOBJ_PAGE ; page <= max_page ; ++page ) {
1340 int mask = VARYOBJ_PAGE_GENS(page);
1341 if (mask & (1<<PSEUDO_STATIC_GENERATION)) {
1342 VARYOBJ_PAGE_GENS(page) = (mask & ~(1<<PSEUDO_STATIC_GENERATION))
1343 | 1<<HIGHEST_NORMAL_GENERATION;
1348 // Now once again promote all objects to pseudo-static just prior to save.
1349 // 'coreparse' makes all pages in regular dynamic space pseudo-static.
1350 // But since immobile objects store their generation, it must be done at save,
1351 // or else it would have to be done on image restart
1352 // which would require writing to a lot of pages for no reason.
1353 void prepare_immobile_space_for_save()
1355 // Don't use the page attributes now - defrag doesn't update them.
1356 lispobj* obj = (lispobj*)IMMOBILE_SPACE_START;
1357 lispobj* limit = (lispobj*)SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value;
1358 while (obj < limit) {
1359 if (other_immediate_lowtag_p(*obj))
1360 assign_generation(obj, PSEUDO_STATIC_GENERATION);
1361 obj += sizetab[widetag_of(*obj)](obj);
1364 obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1365 limit = (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
1366 for ( varyobj_holes = 0 ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
1367 if (immobile_filler_p(obj)) {
1368 struct code* code = (struct code*)obj;
1369 code->debug_info = varyobj_holes;
1370 varyobj_holes = (lispobj)code;
1371 // 0-fill the unused space.
1372 int nwords = sizetab[widetag_of(*obj)](obj);
1373 memset(code->constants, 0,
1374 (nwords * N_WORD_BYTES) - offsetof(struct code, constants));
1375 } else
1376 assign_generation(obj, PSEUDO_STATIC_GENERATION);
1378 if ((lispobj)limit & (IMMOBILE_CARD_BYTES-1)) { // Last page is partially used.
1379 gc_assert(*limit == SIMPLE_ARRAY_FIXNUM_WIDETAG);
1380 // Write an otherwise illegal object at the free pointer.
1381 limit[0] = INSTANCE_WIDETAG; // 0 payload length
1382 limit[1] = 0; // no layout
1386 //// Interface
1388 int immobile_space_handle_wp_violation(void* fault_addr)
1390 low_page_index_t page_index = find_immobile_page_index(fault_addr);
1391 if (page_index < 0) return 0;
1393 os_protect((os_vm_address_t)((lispobj)fault_addr & ~(IMMOBILE_CARD_BYTES-1)),
1394 IMMOBILE_CARD_BYTES, OS_VM_PROT_ALL);
1395 if (page_index >= FIRST_VARYOBJ_PAGE) {
1396 // The free pointer can move up or down. Attempting to insist that a WP
1397 // fault not occur above the free pointer (plus some slack) is not
1398 // threadsafe, so allow it anywhere. More strictness could be imparted
1399 // by tracking the max value attained by the free pointer.
1400 __sync_or_and_fetch(&varyobj_page_touched_bits[(page_index-FIRST_VARYOBJ_PAGE)/32],
1401 1 << (page_index & 31));
1402 } else {
1403 // FIXME: a single bitmap of touched bits would make more sense,
1404 // and the _CLEARED flag doesn't achieve much if anything.
1405 if (!(fixedobj_pages[page_index].attr.parts.flags
1406 & (WRITE_PROTECT|WRITE_PROTECT_CLEARED)))
1407 return 0;
1408 SET_WP_FLAG(page_index, WRITE_PROTECT_CLEARED);
1410 return 1;
1413 // Find the object that encloses pointer.
1414 static int page_attributes_valid = 1; // For verify_space() after defrag
1415 lispobj *
1416 search_immobile_space(void *pointer)
1418 lispobj *start;
1420 if ((lispobj)pointer >= IMMOBILE_SPACE_START
1421 && (lispobj)pointer < SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value) {
1422 low_page_index_t page_index = find_immobile_page_index(pointer);
1423 if ((lispobj)pointer >= IMMOBILE_VARYOBJ_SUBSPACE_START) {
1424 if (page_attributes_valid) {
1425 start = (lispobj*)varyobj_scan_start(page_index);
1426 if (start > (lispobj*)pointer) return NULL;
1427 } else {
1428 start = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1430 lispobj* found = gc_search_space(start, pointer);
1431 return (found && immobile_filler_p(found)) ? 0 : found;
1432 } else if ((lispobj)pointer < SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value) {
1433 char *page_base = (char*)((lispobj)pointer & ~(IMMOBILE_CARD_BYTES-1));
1434 if (page_attributes_valid) {
1435 int spacing = page_obj_align(page_index) << WORD_SHIFT;
1436 int index = ((char*)pointer - page_base) / spacing;
1437 char *begin = page_base + spacing * index;
1438 char *end = begin + (page_obj_size(page_index) << WORD_SHIFT);
1439 if ((char*)pointer < end) return (lispobj*)begin;
1440 } else {
1441 return gc_search_space((lispobj*)page_base, pointer);
1445 return NULL;
1448 // For coalescing holes, we need to scan backwards, which is done by
1449 // looking backwards for a page that contains the start of a
1450 // block of objects one of which must abut 'obj'.
1451 lispobj* find_preceding_object(lispobj* obj)
1453 int page = find_immobile_page_index(obj);
1454 while (1) {
1455 int offset = varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE];
1456 if (offset) { // 0 means the page is empty.
1457 lispobj* start = varyobj_scan_start(page);
1458 if (start < obj) { // Scan from here forward
1459 while (1) {
1460 lispobj* end = start + sizetab[widetag_of(*start)](start);
1461 if (end == obj) return start;
1462 gc_assert(end < obj);
1463 start = end;
1467 if (page == FIRST_VARYOBJ_PAGE) {
1468 gc_assert(obj == low_page_address(FIRST_VARYOBJ_PAGE));
1469 return 0; // Predecessor does not exist
1471 --page;
1475 #include "genesis/vector.h"
1476 #include "genesis/instance.h"
1477 lispobj alloc_layout(lispobj slots)
1479 struct vector* v = VECTOR(slots);
1480 // If INSTANCE_DATA_START is 0, subtract 1 word for the header.
1481 // If 1, subtract 2 words: 1 for the header and 1 for the layout.
1482 if (fixnum_value(v->length) != (LAYOUT_SIZE - INSTANCE_DATA_START - 1))
1483 lose("bad arguments to alloc_layout");
1484 struct instance* l = (struct instance*)
1485 alloc_immobile_obj(MAKE_ATTR(LAYOUT_ALIGN / N_WORD_BYTES,
1486 CEILING(LAYOUT_SIZE,2),
1488 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1489 (LAYOUT_OF_LAYOUT << 32) |
1490 #endif
1491 (LAYOUT_SIZE-1)<<8 | INSTANCE_WIDETAG,
1492 &layout_page_hint);
1493 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1494 l->slots[0] = LAYOUT_OF_LAYOUT;
1495 #endif
1496 memcpy(&l->slots[INSTANCE_DATA_START], v->data,
1497 (LAYOUT_SIZE - INSTANCE_DATA_START - 1)*N_WORD_BYTES);
1499 // Possible efficiency win: make the "wasted" bytes after the layout into a
1500 // simple unboxed array so that heap-walking can skip in one step.
1501 // Probably only a performance issue for MAP-ALLOCATED-OBJECTS,
1502 // since scavenging know to skip by the object alignment anyway.
1503 return make_lispobj(l, INSTANCE_POINTER_LOWTAG);
1506 #include "genesis/symbol.h"
1507 lispobj alloc_sym(lispobj name)
1509 // While there are different "kinds" of symbols in the defragmentation
1510 // logic, we don't distinguish them when allocating,
1511 // on the theory that contiguous allocations are preferable anyway.
1512 struct symbol* s = (struct symbol*)
1513 alloc_immobile_obj(MAKE_ATTR(CEILING(SYMBOL_SIZE,2), // spacing
1514 CEILING(SYMBOL_SIZE,2), // size
1516 (SYMBOL_SIZE-1)<<8 | SYMBOL_WIDETAG,
1517 &symbol_page_hint);
1518 s->value = UNBOUND_MARKER_WIDETAG;
1519 s->hash = 0;
1520 s->info = NIL;
1521 s->name = name;
1522 s->package = NIL;
1523 return make_lispobj(s, OTHER_POINTER_LOWTAG);
1526 #include "genesis/fdefn.h"
1527 lispobj alloc_fdefn(lispobj name)
1529 struct fdefn* f = (struct fdefn*)
1530 alloc_immobile_obj(MAKE_ATTR(CEILING(FDEFN_SIZE,2), // spacing
1531 CEILING(FDEFN_SIZE,2), // size
1533 (FDEFN_SIZE-1)<<8 | FDEFN_WIDETAG,
1534 &fdefn_page_hint);
1535 f->name = name;
1536 f->fun = NIL;
1537 f->raw_addr = 0;
1538 return make_lispobj(f, OTHER_POINTER_LOWTAG);
1541 #if defined(LISP_FEATURE_IMMOBILE_CODE) && defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER)
1542 #include "genesis/funcallable-instance.h"
1543 #define GF_SIZE (sizeof(struct funcallable_instance)/sizeof(lispobj)+2) /* = 6 */
1544 lispobj alloc_generic_function(lispobj slots)
1546 // GFs have no C header file to represent the layout, which is 6 words:
1547 // header, entry-point, fin-function, slots, raw data (x2)
1548 lispobj* obj = (lispobj*)
1549 alloc_immobile_obj(MAKE_ATTR(CEILING(GF_SIZE,2), // spacing
1550 CEILING(GF_SIZE,2), // size
1552 // 5 payload words following the header
1553 ((GF_SIZE-1)<<8) | FUNCALLABLE_INSTANCE_WIDETAG,
1554 // KLUDGE: same page attributes as symbols,
1555 // so use the same hint.
1556 &symbol_page_hint);
1557 ((struct funcallable_instance*)obj)->info[0] = slots;
1558 ((struct funcallable_instance*)obj)->trampoline = (lispobj)(obj + 4);
1559 return make_lispobj(obj, FUN_POINTER_LOWTAG);
1561 #endif
1563 #ifdef LISP_FEATURE_IMMOBILE_CODE
1564 //// Defragmentation
1566 static struct {
1567 char* start;
1568 int n_bytes;
1569 } fixedobj_tempspace, varyobj_tempspace;
1571 // Given an adddress in the target core, return the equivalent
1572 // physical address to read or write during defragmentation
1573 static lispobj* tempspace_addr(void* address)
1575 int byte_index = (char*)address - (char*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1576 gc_assert(immobile_space_p((lispobj)address));
1577 if (byte_index < 0) { // fixedobj subspace
1578 if (fixedobj_tempspace.n_bytes == 0) return address;
1579 byte_index = (char*)address - (char*)IMMOBILE_SPACE_START;
1580 gc_assert(byte_index < fixedobj_tempspace.n_bytes);
1581 return (void*)(fixedobj_tempspace.start + byte_index);
1582 } else { // varyobj subspace
1583 gc_assert(byte_index < varyobj_tempspace.n_bytes);
1584 return (void*)(varyobj_tempspace.start + byte_index);
1588 /* Search for an object during defragmentation */
1589 static lispobj* defrag_search_varyobj_subspace(lispobj addr)
1591 low_page_index_t page = find_immobile_page_index((void*)(long)addr);
1592 lispobj *where = varyobj_scan_start(page);
1593 size_t count;
1594 do {
1595 if (immobile_filler_p(where)) {
1596 count = sizetab[widetag_of(*where)](where);
1597 } else {
1598 gc_assert(forwarding_pointer_p(where));
1599 lispobj *forwarded_obj = native_pointer(forwarding_pointer_value(where));
1600 lispobj *temp_obj = tempspace_addr(forwarded_obj);
1601 count = sizetab[widetag_of(*temp_obj)](temp_obj);
1602 if ((lispobj*)(uword_t)addr < where+count) {
1603 int __attribute__((unused)) widetag = widetag_of(*temp_obj);
1604 gc_assert(widetag == CODE_HEADER_WIDETAG ||
1605 widetag == FDEFN_WIDETAG ||
1606 widetag == FUNCALLABLE_INSTANCE_WIDETAG);
1607 return where;
1610 } while ((where += count) <= (lispobj*)(uword_t)addr);
1611 lose("Can't find jump target");
1614 static void adjust_words(lispobj *where, sword_t n_words)
1616 int i;
1617 for (i=0;i<n_words;++i) {
1618 lispobj ptr = where[i];
1619 if (is_lisp_pointer(ptr) && forwarding_pointer_p(native_pointer(ptr)))
1620 where[i] = forwarding_pointer_value(native_pointer(ptr));
1624 static lispobj adjust_fun_entrypoint(lispobj raw_entry)
1626 if (raw_entry > READ_ONLY_SPACE_END) {
1627 // if not pointing read-only space, then it's neither closure_tramp
1628 // nor funcallable_instance_tramp.
1629 lispobj simple_fun = raw_entry - FUN_RAW_ADDR_OFFSET;
1630 adjust_words(&simple_fun, 1);
1631 return simple_fun + FUN_RAW_ADDR_OFFSET;
1633 return raw_entry; // otherwise it's one of those trampolines
1636 /// Fixup the fdefn at 'where' based on it moving by 'displacement'.
1637 /// 'fdefn_old' is needed for computing the pre-fixup callee if the
1638 /// architecture uses a call-relative instruction.
1639 static void adjust_fdefn_entrypoint(lispobj* where, int displacement,
1640 struct fdefn* fdefn_old)
1642 struct fdefn* fdefn = (struct fdefn*)where;
1643 int callee_adjust = 0;
1644 // Get the tagged object referred to by the fdefn_raw_addr.
1645 lispobj callee_old = fdefn_raw_referent(fdefn_old);
1646 // If it's the undefined function trampoline, or the referent
1647 // did not move, then the callee_adjust stays 0.
1648 // Otherwise we adjust the rel32 field by the change in callee address.
1649 if (callee_old && forwarding_pointer_p(native_pointer(callee_old))) {
1650 lispobj callee_new = forwarding_pointer_value(native_pointer(callee_old));
1651 callee_adjust = callee_new - callee_old;
1653 #ifdef LISP_FEATURE_X86_64
1654 *(int*)((char*)&fdefn->raw_addr + 1) += callee_adjust - displacement;
1655 #else
1656 #error "Can't adjust fdefn_raw_addr for this architecture"
1657 #endif
1660 // Fix the layout of OBJ, and return the layout's address in tempspace.
1661 struct layout* fix_object_layout(lispobj* obj)
1663 // This works on instances, funcallable instances (and/or closures)
1664 // but the latter only if the layout is in the header word.
1665 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1666 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG
1667 || widetag_of(*obj) == FUNCALLABLE_INSTANCE_WIDETAG
1668 || widetag_of(*obj) == CLOSURE_WIDETAG);
1669 #else
1670 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1671 #endif
1672 lispobj layout = instance_layout(obj);
1673 if (layout == 0) return 0;
1674 if (forwarding_pointer_p(native_pointer(layout))) { // usually
1675 layout = forwarding_pointer_value(native_pointer(layout));
1676 set_instance_layout(obj, layout);
1678 struct layout* native_layout = (struct layout*)
1679 tempspace_addr(native_pointer(layout));
1680 gc_assert(widetag_of(native_layout->header) == INSTANCE_WIDETAG);
1681 gc_assert(instance_layout((lispobj*)native_layout) == LAYOUT_OF_LAYOUT);
1682 return native_layout;
1685 static lispobj follow_fp(lispobj ptr)
1687 if (forwarding_pointer_p(native_pointer(ptr)))
1688 return forwarding_pointer_value(native_pointer(ptr));
1689 else
1690 return ptr;
1693 /// It's tricky to try to use the scavtab[] functions for fixing up moved
1694 /// objects, because scavenger functions might invoke transport functions.
1695 /// The best approach is to do an explicit switch over all object types.
1696 #include "genesis/hash-table.h"
1697 static void fixup_space(lispobj* where, size_t n_words)
1699 lispobj* end = where + n_words;
1700 lispobj header_word;
1701 int widetag;
1702 long size;
1703 int static_space_p = ((lispobj)where == STATIC_SPACE_START);
1704 struct code* code;
1706 while (where < end) {
1707 gc_assert(!forwarding_pointer_p(where));
1708 header_word = *where;
1709 if (is_cons_half(header_word)) {
1710 adjust_words(where, 2); // A cons.
1711 where += 2;
1712 continue;
1714 widetag = widetag_of(header_word);
1715 size = sizetab[widetag](where);
1716 switch (widetag) {
1717 default:
1718 if (!unboxed_obj_widetag_p(widetag))
1719 lose("Unhandled widetag in fixup_space: %p\n", (void*)header_word);
1720 break;
1721 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1722 case FUNCALLABLE_INSTANCE_WIDETAG:
1723 #endif
1724 case INSTANCE_WIDETAG:
1725 instance_scan(adjust_words, where+1,
1726 instance_length(header_word) | 1,
1727 fix_object_layout(where)->bitmap);
1728 break;
1729 case CODE_HEADER_WIDETAG:
1730 // Fixup the constant pool.
1731 adjust_words(where+1, code_header_words(header_word)-1);
1732 // Fixup all embedded simple-funs
1733 code = (struct code*)where;
1734 for_each_simple_fun(i, f, code, 1, {
1735 f->self = adjust_fun_entrypoint(f->self);
1736 adjust_words(SIMPLE_FUN_SCAV_START(f), SIMPLE_FUN_SCAV_NWORDS(f));
1738 if (code->fixups)
1739 fixup_immobile_refs(follow_fp, code->fixups, code);
1740 break;
1741 case CLOSURE_WIDETAG:
1742 where[1] = adjust_fun_entrypoint(where[1]);
1743 // FALLTHROUGH_INTENDED
1744 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1745 case FUNCALLABLE_INSTANCE_WIDETAG:
1746 #endif
1747 // skip the trampoline word at where[1]
1748 adjust_words(where+2, size-2);
1749 break;
1750 case FDEFN_WIDETAG:
1751 adjust_words(where+1, 2);
1752 // If fixed-size objects (hence FDEFNs) are movable, then fixing the
1753 // raw address can not be done here, because it is impossible to compute
1754 // the absolute jump target - we don't know what the fdefn's original
1755 // address was to compute a pc-relative address. So we do those while
1756 // permuting the FDEFNs. But because static fdefns do not move,
1757 // we do process their raw address slot here.
1758 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
1759 if (static_space_p)
1760 #endif
1761 adjust_fdefn_entrypoint(where, 0, (struct fdefn*)where);
1762 break;
1764 // Special case because we might need to mark hashtables
1765 // as needing rehash.
1766 case SIMPLE_VECTOR_WIDETAG:
1767 if ((HeaderValue(header_word) & 0xFF) == subtype_VectorValidHashing) {
1768 struct vector* v = (struct vector*)where;
1769 lispobj* data = v->data;
1770 gc_assert(v->length > 0 &&
1771 lowtag_of(data[0]) == INSTANCE_POINTER_LOWTAG &&
1772 !(fixnum_value(v->length) & 1)); // length must be even
1773 boolean needs_rehash = 0;
1774 int i;
1775 for (i = fixnum_value(v->length)-1 ; i>=0 ; --i) {
1776 lispobj ptr = data[i];
1777 if (is_lisp_pointer(ptr) && forwarding_pointer_p(native_pointer(ptr))) {
1778 data[i] = forwarding_pointer_value(native_pointer(ptr));
1779 needs_rehash = 1;
1782 if (needs_rehash) {
1783 struct hash_table *ht = (struct hash_table*)native_pointer(v->data[0]);
1784 ht->needs_rehash_p = T;
1786 break;
1787 } else {
1788 // FALLTHROUGH_INTENDED
1790 // All the other array header widetags.
1791 case SIMPLE_ARRAY_WIDETAG:
1792 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
1793 case COMPLEX_CHARACTER_STRING_WIDETAG:
1794 #endif
1795 case COMPLEX_BASE_STRING_WIDETAG:
1796 case COMPLEX_VECTOR_NIL_WIDETAG:
1797 case COMPLEX_BIT_VECTOR_WIDETAG:
1798 case COMPLEX_VECTOR_WIDETAG:
1799 case COMPLEX_ARRAY_WIDETAG:
1800 // And the other entirely boxed objects.
1801 case SYMBOL_WIDETAG:
1802 case VALUE_CELL_WIDETAG:
1803 case WEAK_POINTER_WIDETAG:
1804 case RATIO_WIDETAG:
1805 case COMPLEX_WIDETAG:
1806 // Use the sizing functions for generality.
1807 // Symbols can contain strange header bytes,
1808 // and vectors might have a padding word, etc.
1809 adjust_words(where+1, size-1);
1810 break;
1812 where += size;
1816 int* immobile_space_reloc_index;
1817 int* immobile_space_relocs;
1819 static int calc_n_pages(int n_objects, int words_per_object)
1821 words_per_object = CEILING(words_per_object, 2);
1822 int objects_per_page = WORDS_PER_PAGE / words_per_object;
1823 return (n_objects + objects_per_page - 1) / objects_per_page;
1826 // Take and return an untagged pointer, or 0 if the object did not survive GC.
1827 static lispobj* get_load_address(lispobj* old)
1829 if (forwarding_pointer_p(old))
1830 return native_pointer(forwarding_pointer_value(old));
1831 gc_assert(immobile_filler_p(old));
1832 return 0;
1835 // This does not accept (SIMPLE-ARRAY NIL (*))
1836 // (You'd have a pretty bad time trying making a symbol like that)
1837 static int schar(struct vector* string, int index)
1839 #ifdef LISP_FEATURE_SB_UNICODE
1840 if (widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG)
1841 return ((int*)string->data)[index];
1842 #endif
1843 return ((char*)string->data)[index];
1846 #include "genesis/package.h"
1847 #define N_SYMBOL_KINDS 4
1849 // Return an integer 0..3 telling which block of symbols to relocate 'sym' into.
1850 // This is the same as the "symbol kind" in the allocator.
1851 // 0 = uninterned, 1 = keyword, 2 = other interned, 3 = special var
1852 static int classify_symbol(lispobj* obj)
1854 struct symbol* symbol = (struct symbol*)obj;
1855 if (symbol->package == NIL) return 0;
1856 struct vector* package_name = (struct vector*)
1857 native_pointer(((struct package*)native_pointer(symbol->package))->_name);
1858 if (widetag_of(package_name->header) == SIMPLE_BASE_STRING_WIDETAG
1859 && !strcmp((char*)package_name->data, "KEYWORD"))
1860 return 1;
1861 struct vector* symbol_name = VECTOR(symbol->name);
1862 if (symbol_name->length >= make_fixnum(2) &&
1863 schar(symbol_name, 0) == '*' &&
1864 schar(symbol_name, fixnum_value(symbol_name->length)-1) == '*')
1865 return 3;
1866 return 2;
1869 static char* compute_defrag_start_address()
1871 // For technical reasons, objects on the first few pages created by genesis
1872 // must never move at all. So figure out where the end of that subspace is.
1873 lispobj* obj = (lispobj*)IMMOBILE_SPACE_START;
1874 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1875 while (instance_layout(obj) != LAYOUT_OF_PACKAGE) {
1876 obj = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1877 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1879 // Now find a page that does NOT have a package.
1880 do {
1881 obj = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1882 } while (widetag_of(*obj) == INSTANCE_WIDETAG
1883 && instance_layout(obj) == LAYOUT_OF_PACKAGE);
1884 return (char*)obj;
1887 void defrag_immobile_space(int* components, boolean verbose)
1889 // Find the starting address of fixed-size objects that will undergo defrag.
1890 // Never move the first few pages of LAYOUTs or PACKAGEs created by genesis.
1891 // If codegen becomes smarter, things like layout of FUNCTION and some
1892 // some others can be used as immediate constants in compiled code.
1893 // With initial packages, it's mainly a debugging convenience that they not move.
1894 char* defrag_base = compute_defrag_start_address();
1895 low_page_index_t page_index = find_immobile_page_index(defrag_base);
1896 lispobj* addr;
1897 int i;
1899 // Count the number of symbols, fdefns, and layouts that will be relocated
1900 unsigned int obj_type_histo[64], sym_kind_histo[4];
1901 bzero(obj_type_histo, sizeof obj_type_histo);
1902 bzero(sym_kind_histo, sizeof sym_kind_histo);
1904 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
1905 for ( ; page_index <= max_used_fixedobj_page ; ++page_index) {
1906 int obj_spacing = page_obj_align(page_index) << WORD_SHIFT;
1907 if (obj_spacing) {
1908 lispobj* obj = low_page_address(page_index);
1909 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1910 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1911 lispobj word = *obj;
1912 if (!fixnump(word)) {
1913 if (widetag_of(word) == SYMBOL_WIDETAG)
1914 ++sym_kind_histo[classify_symbol(obj)];
1915 else
1916 ++obj_type_histo[widetag_of(word)/4];
1921 gc_assert(obj_type_histo[INSTANCE_WIDETAG/4]);
1923 // Calculate space needed for fixedobj pages after defrag.
1924 // page order is: layouts, fdefns, GFs, symbols
1925 int n_layout_pages = calc_n_pages(obj_type_histo[INSTANCE_WIDETAG/4],
1926 LAYOUT_ALIGN / N_WORD_BYTES);
1927 int n_fdefn_pages = calc_n_pages(obj_type_histo[FDEFN_WIDETAG/4], FDEFN_SIZE);
1928 int n_fin_pages = calc_n_pages(obj_type_histo[FUNCALLABLE_INSTANCE_WIDETAG/4],
1929 6); // KLUDGE
1930 #if !(defined(LISP_FEATURE_IMMOBILE_CODE) && defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER))
1931 gc_assert(n_fin_pages == 0);
1932 #endif
1933 char* layout_alloc_ptr = defrag_base;
1934 char* fdefn_alloc_ptr = layout_alloc_ptr + n_layout_pages * IMMOBILE_CARD_BYTES;
1935 char* fin_alloc_ptr = fdefn_alloc_ptr + n_fdefn_pages * IMMOBILE_CARD_BYTES;
1936 char* symbol_alloc_ptr[N_SYMBOL_KINDS+1];
1937 symbol_alloc_ptr[0] = fin_alloc_ptr + n_fin_pages * IMMOBILE_CARD_BYTES;
1938 for (i=0; i<N_SYMBOL_KINDS ; ++i)
1939 symbol_alloc_ptr[i+1] = symbol_alloc_ptr[i]
1940 + calc_n_pages(sym_kind_histo[i], SYMBOL_SIZE) * IMMOBILE_CARD_BYTES;
1941 char* ending_alloc_ptr = symbol_alloc_ptr[N_SYMBOL_KINDS];
1943 fixedobj_tempspace.n_bytes = ending_alloc_ptr - (char*)IMMOBILE_SPACE_START;
1944 fixedobj_tempspace.start = calloc(fixedobj_tempspace.n_bytes, 1);
1945 // Copy the first few pages (the permanent pages) from immobile space
1946 // into the temporary copy, so that tempspace_addr()
1947 // does not have to return the unadjusted addr if below defrag_base.
1948 memcpy(fixedobj_tempspace.start, (char*)IMMOBILE_SPACE_START,
1949 (lispobj)defrag_base - IMMOBILE_SPACE_START);
1950 #endif
1952 // Compute where each code component will be moved to.
1953 int n_code_components = 0;
1954 for (i=0 ; components[i*2] ; ++i) {
1955 addr = (lispobj*)(long)components[i*2];
1956 gc_assert(lowtag_of((lispobj)addr) == OTHER_POINTER_LOWTAG);
1957 addr = native_pointer((lispobj)addr);
1958 int widetag = widetag_of(*addr);
1959 lispobj new_vaddr = 0;
1960 // FIXME: generalize
1961 gc_assert(widetag == CODE_HEADER_WIDETAG);
1962 if (!immobile_filler_p(addr)) {
1963 ++n_code_components;
1964 new_vaddr = IMMOBILE_VARYOBJ_SUBSPACE_START + varyobj_tempspace.n_bytes;
1965 varyobj_tempspace.n_bytes += sizetab[widetag](addr) << WORD_SHIFT;
1967 components[i*2+1] = new_vaddr;
1969 varyobj_tempspace.start = calloc(varyobj_tempspace.n_bytes, 1);
1971 if (verbose)
1972 printf("%d+%d+%d+%d objects... ",
1973 obj_type_histo[INSTANCE_WIDETAG/4],
1974 obj_type_histo[FDEFN_WIDETAG/4],
1975 (sym_kind_histo[0]+sym_kind_histo[1]+
1976 sym_kind_histo[2]+sym_kind_histo[3]),
1977 n_code_components);
1979 // Permute varyobj space into tempspace and deposit forwarding pointers.
1980 lispobj new_vaddr;
1981 for (i=0 ; components[i*2] ; ++i) {
1982 if ((new_vaddr = components[i*2+1]) != 0) {
1983 addr = native_pointer(components[i*2]);
1984 memcpy(tempspace_addr((void*)new_vaddr), addr,
1985 sizetab[widetag_of(*addr)](addr) << WORD_SHIFT);
1986 int displacement = new_vaddr - (lispobj)addr;
1987 switch (widetag_of(*addr)) {
1988 case CODE_HEADER_WIDETAG:
1989 for_each_simple_fun(index, fun, (struct code*)addr, 1, {
1990 set_forwarding_pointer((lispobj*)fun,
1991 make_lispobj((char*)fun + displacement,
1992 FUN_POINTER_LOWTAG));
1994 break;
1996 set_forwarding_pointer(addr,
1997 make_lispobj((void*)new_vaddr,
1998 OTHER_POINTER_LOWTAG));
2002 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2003 // Permute fixed-sized object pages and deposit forwarding pointers.
2004 for ( page_index = find_immobile_page_index(defrag_base) ;
2005 page_index <= max_used_fixedobj_page ; ++page_index) {
2006 int obj_spacing = page_obj_align(page_index) << WORD_SHIFT;
2007 if (!obj_spacing) continue;
2008 lispobj* obj = low_page_address(page_index);
2009 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
2010 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
2011 lispobj word = *obj;
2012 if (fixnump(word)) continue;
2013 char** alloc_ptr;
2014 int lowtag = OTHER_POINTER_LOWTAG;
2015 int widetag = widetag_of(word);
2016 switch (widetag) {
2017 case INSTANCE_WIDETAG:
2018 alloc_ptr = &layout_alloc_ptr;
2019 lowtag = INSTANCE_POINTER_LOWTAG;
2020 break;
2021 case FUNCALLABLE_INSTANCE_WIDETAG:
2022 alloc_ptr = &fin_alloc_ptr;
2023 lowtag = FUN_POINTER_LOWTAG;
2024 break;
2025 case FDEFN_WIDETAG:
2026 alloc_ptr = &fdefn_alloc_ptr;
2027 break;
2028 case SYMBOL_WIDETAG:
2029 alloc_ptr = &symbol_alloc_ptr[classify_symbol(obj)];
2030 break;
2031 default:
2032 lose("Unexpected widetag");
2034 lispobj* new = (lispobj*)*alloc_ptr;
2035 lispobj end = (lispobj)new + obj_spacing;
2036 #define ALIGN_MASK (IMMOBILE_CARD_BYTES - 1)
2037 if ((end & ALIGN_MASK) < ((lispobj)new & ALIGN_MASK) // wrapped
2038 && (end & ALIGN_MASK) != 0) // ok if exactly on the boundary
2039 new = (lispobj*)(end & ~ALIGN_MASK); // snap to page
2040 #undef ALIGN_MASK
2041 memcpy(tempspace_addr(new), obj, sizetab[widetag](obj) << WORD_SHIFT);
2042 set_forwarding_pointer(obj, make_lispobj(new, lowtag));
2043 *alloc_ptr = (char*)new + obj_spacing;
2046 #ifdef LISP_FEATURE_X86_64
2047 // Fixup JMP offset in fdefns, and self pointers in funcallable instances.
2048 // The former can not be done in the same pass as space permutation,
2049 // because we don't know the order in which a generic function and its
2050 // related fdefn will be reached. Were this attempted in a single pass,
2051 // it could miss a GF that will be moved after the fdefn is moved.
2052 // And it can't be done in fixup_space() because that does not know the
2053 // original address of each fdefn, so can't compute the absolute callee.
2054 for ( page_index = find_immobile_page_index(defrag_base) ;
2055 page_index <= max_used_fixedobj_page ; ++page_index) {
2056 int obj_spacing = page_obj_align(page_index) << WORD_SHIFT;
2057 if (!obj_spacing) continue;
2058 lispobj* obj = low_page_address(page_index);
2059 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
2060 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
2061 if (fixnump(*obj)) continue;
2062 gc_assert(forwarding_pointer_p(obj));
2063 lispobj* new = native_pointer(forwarding_pointer_value(obj));
2064 switch (widetag_of(*tempspace_addr(new))) {
2065 case FDEFN_WIDETAG:
2066 // Fix displacement in JMP or CALL instruction.
2067 adjust_fdefn_entrypoint(tempspace_addr(new),
2068 (char*)new - (char*)obj,
2069 (struct fdefn*)obj);
2070 break;
2071 case FUNCALLABLE_INSTANCE_WIDETAG:
2072 tempspace_addr(new)[1] = (lispobj)(new + 4);
2073 break;
2077 #endif /* LISP_FEATURE_X86_64 */
2078 #endif /* DEFRAGMENT_FIXEDOBJ_SUBSPACE */
2080 #ifdef LISP_FEATURE_X86_64
2081 // Fix displacements in JMP and CALL instructions in code objects.
2082 // There are 2 arrays in use:
2083 // - the relocs[] array contains the address of any machine instruction
2084 // that needs to be altered on account of space relocation.
2085 // - the reloc_index[] array identifes the code component each reloc belongs to.
2086 // It is an array of pairs:
2087 // comp_ptr1, index1, comp_ptr2, index2 ... comp_ptrN, indexN, 0, index_max
2088 // The index following a component specifies the starting index within the
2089 // relocs[] array of the first reloc belonging to the respective component.
2090 // The ending reloc can be deduced from the next component's first reloc.
2091 for (i = 0 ; immobile_space_reloc_index[i*2] ; ++i) {
2092 lispobj code = immobile_space_reloc_index[i*2] - OTHER_POINTER_LOWTAG;
2093 lispobj load_addr;
2094 if (code >= READ_ONLY_SPACE_START && code < READ_ONLY_SPACE_END)
2095 load_addr = code; // This code can not be moved or GCed.
2096 else
2097 load_addr = (lispobj)get_load_address((lispobj*)code);
2098 if (!load_addr) continue; // Skip code that was dropped by GC
2099 int reloc_index = immobile_space_reloc_index[i*2+1];
2100 int end_reloc_index = immobile_space_reloc_index[i*2+3];
2101 for ( ; reloc_index < end_reloc_index ; ++reloc_index ) {
2102 unsigned char* inst_addr = (unsigned char*)(long)immobile_space_relocs[reloc_index];
2103 gc_assert(*inst_addr == 0xE8 || *inst_addr == 0xE9);
2104 unsigned int target_addr = (int)(long)inst_addr + 5 + *(int*)(inst_addr+1);
2105 int target_adjust = 0;
2106 // Both this code and the jumped-to code can move.
2107 // For this component, adjust by the displacement by (old - new).
2108 // If the jump target moved, also adjust by its (new - old).
2109 // The target address can point to one of:
2110 // - an FDEFN raw addr slot (fixedobj subspace)
2111 // - funcallable-instance with self-contained trampoline (ditto)
2112 // - a simple-fun that was statically linked (varyobj subspace)
2113 if (immobile_space_p(target_addr)) {
2114 lispobj *obj = target_addr < IMMOBILE_VARYOBJ_SUBSPACE_START
2115 ? search_immobile_space((void*)(uword_t)target_addr)
2116 : defrag_search_varyobj_subspace(target_addr);
2117 if (forwarding_pointer_p(obj))
2118 target_adjust = (int)((char*)native_pointer(forwarding_pointer_value(obj))
2119 - (char*)obj);
2121 // If the instruction to fix has moved, then adjust for
2122 // its new address, and perform the fixup in tempspace.
2123 // Otherwise perform the fixup where the instruction is now.
2124 char* fixup_loc = (immobile_space_p((lispobj)inst_addr) ?
2125 (char*)tempspace_addr(inst_addr - code + load_addr) :
2126 (char*)inst_addr) + 1;
2127 *(int*)fixup_loc += target_adjust + (code - load_addr);
2130 #endif
2131 free(immobile_space_relocs);
2132 free(immobile_space_reloc_index);
2134 // Fix Lisp pointers in static, immobile, and dynamic spaces
2135 fixup_space((lispobj*)STATIC_SPACE_START,
2136 (SYMBOL(STATIC_SPACE_FREE_POINTER)->value
2137 - STATIC_SPACE_START) >> WORD_SHIFT);
2139 // Objects in immobile space are physically at 'tempspace',
2140 // but logically at their natural address. Perform fixups
2141 // at their current physical address.
2142 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2143 fixup_space((lispobj*)fixedobj_tempspace.start,
2144 fixedobj_tempspace.n_bytes >> WORD_SHIFT);
2145 #else
2146 fixup_space((lispobj*)IMMOBILE_SPACE_START,
2147 IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE >> WORD_SHIFT);
2148 #endif
2149 fixup_space((lispobj*)varyobj_tempspace.start,
2150 varyobj_tempspace.n_bytes >> WORD_SHIFT);
2152 // Dynamic space
2153 // We can safely ignore allocation region boundaries.
2154 fixup_space((lispobj*)DYNAMIC_SPACE_START,
2155 ((lispobj)
2156 #ifdef reg_ALLOC
2157 dynamic_space_free_pointer
2158 #else
2159 SymbolValue(ALLOCATION_POINTER,0)
2160 #endif
2161 - DYNAMIC_SPACE_START) >> WORD_SHIFT);
2163 // Copy the spaces back where they belong.
2165 // Fixed-size objects: don't copy below the defrag_base - the first few
2166 // pages are totally static in regard to both lifetime and placement.
2167 // (It would "work" to copy them back - since they were copied into
2168 // the temp space, but it's just wasting time to do so)
2169 lispobj old_free_ptr;
2170 lispobj free_ptr;
2171 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2172 int n_static_bytes = ((lispobj)defrag_base - IMMOBILE_SPACE_START);
2173 memcpy((char*)defrag_base,
2174 fixedobj_tempspace.start + n_static_bytes,
2175 fixedobj_tempspace.n_bytes - n_static_bytes);
2176 // Zero-fill the unused remainder
2177 old_free_ptr = SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value;
2178 free_ptr = IMMOBILE_SPACE_START + fixedobj_tempspace.n_bytes;
2179 bzero((char*)free_ptr, old_free_ptr - free_ptr);
2180 SYMBOL(IMMOBILE_FIXEDOBJ_FREE_POINTER)->value = free_ptr;
2181 #endif
2183 // Variable-size object pages.
2184 memcpy((char*)IMMOBILE_VARYOBJ_SUBSPACE_START,
2185 varyobj_tempspace.start, varyobj_tempspace.n_bytes);
2186 // Zero-fill the unused remainder
2187 old_free_ptr = SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
2188 free_ptr = IMMOBILE_VARYOBJ_SUBSPACE_START + varyobj_tempspace.n_bytes;
2189 bzero((char*)free_ptr, old_free_ptr - free_ptr);
2190 SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value = free_ptr;
2191 if (free_ptr & (IMMOBILE_CARD_BYTES-1)) { // unless page-aligned
2192 int remainder = IMMOBILE_CARD_BYTES - (free_ptr & (IMMOBILE_CARD_BYTES-1));
2193 ((lispobj*)free_ptr)[0] = SIMPLE_ARRAY_FIXNUM_WIDETAG;
2194 ((lispobj*)free_ptr)[1] = make_fixnum((remainder >> WORD_SHIFT) - 2);
2197 free(components);
2198 #if 0
2199 // It's easy to mess things up, so assert correctness before saving a core.
2200 printf("verifying defrag\n");
2201 page_attributes_valid = 0;
2202 verify_gc();
2203 printf("verify passed\n");
2204 #endif
2205 free(fixedobj_tempspace.start);
2206 free(varyobj_tempspace.start);
2208 #endif
2210 void verify_immobile_page_protection(int keep_gen, int new_gen)
2212 low_page_index_t page;
2213 lispobj* end = (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
2214 low_page_index_t end_page = find_immobile_page_index((char*)end-1);
2215 lispobj* obj;
2217 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2218 if (!varyobj_page_touched(page)) {
2219 lispobj* page_begin = low_page_address(page);
2220 lispobj* page_end = page_begin + WORDS_PER_PAGE;
2221 // Assert that there are no old->young pointers.
2222 obj = varyobj_scan_start(page);
2223 // Never scan past the free pointer.
2224 // FIXME: It is is supposed to work to scan past the free pointer
2225 // on the last page, but the allocator needs to plop an array header there,
2226 // and sometimes it doesn't.
2227 lispobj* varyobj_free_ptr = (lispobj*)(SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value);
2228 if (page_end > varyobj_free_ptr) page_end = varyobj_free_ptr;
2229 for ( ; obj < page_end ; obj += sizetab[widetag_of(*obj)](obj) ) {
2230 if (!immobile_filler_p(obj)
2231 && varyobj_points_to_younger_p(obj, __immobile_obj_gen_bits(obj),
2232 keep_gen, new_gen,
2233 (char*)page_begin, (char*)page_end))
2234 lose("page WP bit on page %d is wrong\n", page);
2240 // Fixup immediate values that encode Lisp object addresses
2241 // in immobile space.
2242 #include "forwarding-ptr.h"
2243 #ifdef LISP_FEATURE_X86_64
2244 void fixup_immobile_refs(lispobj (*fixup_lispobj)(lispobj),
2245 lispobj fixups, struct code* code)
2247 struct varint_unpacker unpacker;
2248 varint_unpacker_init(&unpacker, fixups);
2249 char* instructions = (char*)((lispobj*)code + code_header_words(code->header));
2250 int prev_loc = 0, loc;
2251 while (varint_unpack(&unpacker, &loc) && loc != 0) {
2252 // For extra compactness, each loc is relative to the prior,
2253 // so that the magnitudes are smaller.
2254 loc += prev_loc;
2255 prev_loc = loc;
2256 int* fixup_where = (int*)(instructions + loc);
2257 lispobj ptr = (lispobj)(*fixup_where);
2258 if (is_lisp_pointer(ptr)) {
2259 lispobj fixed = fixup_lispobj(ptr);
2260 if (fixed != ptr)
2261 *fixup_where = fixed;
2262 } else {
2263 gc_assert(IMMOBILE_SPACE_START <= ptr &&
2264 ptr < (IMMOBILE_SPACE_START+IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE));
2265 // It's an absolute interior pointer. search_immobile_space() works
2266 // at this point, because the page attributes on the pointee's page are valid
2267 lispobj* obj = search_immobile_space((void*)ptr);
2268 if (forwarding_pointer_p(obj)) {
2269 lispobj fpval = forwarding_pointer_value(obj);
2270 *fixup_where = (int)(long)native_pointer(fpval) + (ptr - (lispobj)obj);
2275 #endif
2277 #ifdef VERIFY_PAGE_GENS
2278 void check_fixedobj_page(int page)
2280 // Every page should have a 'gens' mask which exactly reflects
2281 // the aggregate over all objects on that page. Verify that invariant,
2282 // checking all pages, not just the ones below the free pointer.
2283 int genmask, obj_size, obj_spacing, i, all_ok = 1;
2284 lispobj *obj, *limit, header;
2285 int sees_younger = 0;
2287 obj_size = page_obj_size(page);
2288 obj_spacing = page_obj_align(page);
2289 obj = low_page_address(page);
2290 limit = obj + WORDS_PER_PAGE - obj_spacing;
2291 genmask = 0;
2292 if (obj_size == 0) {
2293 for (i=0; i<WORDS_PER_PAGE; ++i)
2294 gc_assert(obj[i]==0);
2295 gc_assert(fixedobj_pages[page].gens ==0);
2296 return;
2298 for ( ; obj <= limit ; obj += obj_spacing ) {
2299 header = *obj;
2300 if (!fixnump(header)) {
2301 int gen = __immobile_obj_gen_bits(obj);
2302 gc_assert(0 <= gen && gen <= PSEUDO_STATIC_GENERATION);
2303 genmask |= 1<<gen;
2304 if (fixedobj_points_to_younger_p(obj, obj_size, gen, 0xff, 0xff))
2305 sees_younger = 1;
2308 // It's not wrong if the gen0 bit is set spuriously, but it should only
2309 // happen at most once, on the first GC after image startup.
2310 // At all other times, the invariant should hold that if the freelist
2311 // indicated that space was available, and the new pointer differs,
2312 // then some gen0 object exists on the page.
2313 // The converse is true because of pseudo-atomicity of the allocator:
2314 // if some thread claimed a hole, then it also updated the freelist.
2315 // If it died before doing the latter, then the object allegedly created
2316 // was never really live, so won't contain any pointers.
2317 if (fixedobj_pages[page].gens != genmask
2318 && fixedobj_pages[page].gens != (genmask|1)) {
2319 fprintf(stderr, "Page #x%x @ %p: stored mask=%x actual=%x\n",
2320 page, low_page_address(page),
2321 fixedobj_pages[page].gens, genmask);
2322 all_ok = 0;
2324 if (fixedobj_page_wp(page) && sees_younger) {
2325 fprintf(stderr, "Page #x%x @ %p: WP is wrong\n",
2326 page, low_page_address(page));
2327 all_ok = 0;
2329 gc_assert(all_ok);
2332 int n_immobile_objects;
2333 int *immobile_objects, *immobile_objects_limit;
2335 int comparator_eq(const void* a, const void* b) {
2336 return *(int*)a - *(int*)b;
2339 // Find the largest item less than or equal.
2340 // (useful for finding the object that contains a given pointer)
2341 int comparator_le(const void* a, const void* b) {
2342 int diff = *(int*)a - *(int*)b;
2343 if (diff <= 0) return diff;
2344 // If looking to the right would see an item strictly greater
2345 // than the sought key, or there is nothing to the right,
2346 // then deem this an exact match.
2347 if (b == (void*)immobile_objects_limit || ((int*)b)[1] > *(int*)a) return 0;
2348 return 1;
2351 // Find the smallest item greater than or equal.
2352 // useful for finding the lowest item at or after a page base address.
2353 int comparator_ge(const void* a, const void* b) {
2354 int diff = *(int*)a - *(int*)b;
2355 if (diff >= 0) return diff;
2356 // If looking to the left would see an item strictly less
2357 // than the sought key, or there is nothing to the left
2358 // then deem this an exact match.
2359 if (b == (void*)immobile_objects || ((int*)b)[-1] < *(int*)a) return 0;
2360 return -1;
2363 void check_varyobj_pages()
2365 // 1. Check that a linear scan sees only valid object headers,
2366 // and that it terminates exactly at IMMOBILE_CODE_FREE_POINTER.
2367 lispobj* obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
2368 lispobj* end = (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
2369 low_page_index_t end_page = find_immobile_page_index((char*)end-1);
2371 n_immobile_objects = 0;
2372 while (obj < end) {
2373 lispobj word = *obj;
2374 gc_assert(other_immediate_lowtag_p(word));
2375 int n_words = sizetab[widetag_of(word)](obj);
2376 obj += n_words;
2377 ++n_immobile_objects;
2379 gc_assert(obj == end);
2381 // 2. Check that all scan_start_offsets are plausible.
2382 // Begin by collecting all object header locations into an array;
2383 immobile_objects = calloc(n_immobile_objects, sizeof (lispobj));
2384 immobile_objects_limit = immobile_objects + n_immobile_objects - 1;
2385 obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
2386 int i = 0;
2387 while (obj < end) {
2388 immobile_objects[i++] = (lispobj)obj;
2389 lispobj word = *obj;
2390 int n_words = sizetab[widetag_of(word)](obj);
2391 obj += n_words;
2393 // Check that each page's scan start is a known immobile object
2394 // and that it is the right object.
2395 low_page_index_t page;
2396 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2397 lispobj page_addr = (lispobj)low_page_address(page);
2398 int* found_below = bsearch(&page_addr, immobile_objects, n_immobile_objects,
2399 sizeof (int), comparator_le);
2400 int* found_above = bsearch(&page_addr, immobile_objects, n_immobile_objects,
2401 sizeof (int), comparator_ge);
2402 int stored_scan_start = (int)(long)varyobj_scan_start(page);
2403 lispobj* scan_start_obj = (lispobj*)(long)*found_below;
2404 if (scan_start_obj != (lispobj*)(long)stored_scan_start) {
2405 //printf("page %d: found-below=%p stored=%p\n", page, scan_start_obj, stored_scan_start);
2406 while (immobile_filler_p(scan_start_obj)) {
2407 int nwords = sizetab[widetag_of(*scan_start_obj)](scan_start_obj);
2408 // printf("skipping %d words to %p\n", nwords, scan_start_obj + nwords);
2409 scan_start_obj += nwords;
2410 // the stored scan start does not guarantee that it points
2411 // to a non-hole; we only assert that it *probably* does not.
2412 // As such, when computing the "correct" value, we allow
2413 // any value in between the legal bounding values for it.
2414 if ((int)(long)scan_start_obj == stored_scan_start)
2415 break;
2416 // If you hit the free pointer, or run off the page,
2417 // then the page is completely empty.
2418 if (scan_start_obj == (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value
2419 || scan_start_obj >= (lispobj*)low_page_address(page+1)) {
2420 scan_start_obj = low_page_address(page+1);
2421 break;
2425 if (scan_start_obj != (lispobj*)(long)stored_scan_start)
2426 lose("page %d: stored_scan_start=%p does not match found %p\n",
2427 page, stored_scan_start, *found_below);
2428 if (found_below != found_above) {
2429 // the object below must touch this page.
2430 // if it didn't, there should be a higher object below.
2431 lispobj* below = (lispobj*)(long)*found_below;
2432 int n_words = sizetab[widetag_of(*below)](below);
2433 lispobj* end = below + n_words;
2434 gc_assert(end > (lispobj*)page_addr);
2437 free(immobile_objects);
2439 // 3. The generation mask for each page is exactly the union
2440 // of generation numbers of object headers on the page.
2441 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2442 if (!varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE])
2443 continue; // page is all holes or never used
2444 obj = varyobj_scan_start(page);
2445 lispobj word = *obj;
2446 int n_words = sizetab[widetag_of(word)](obj);
2447 // Skip the first object if it doesn't start on this page.
2448 if (obj < (lispobj*)low_page_address(page)) obj += n_words;
2449 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
2450 lispobj* freeptr = (lispobj*)SYMBOL(IMMOBILE_SPACE_FREE_POINTER)->value;
2451 if (limit > freeptr) limit = freeptr;
2452 int mask = 0;
2453 for ( ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
2454 int gen = __immobile_obj_gen_bits(obj);
2455 if (immobile_filler_p(obj)) {
2456 gc_assert(gen == 0);
2457 } else {
2458 gc_assert(0 <= gen && gen <= PSEUDO_STATIC_GENERATION);
2459 mask |= 1 << gen;
2462 gc_assert(mask == VARYOBJ_PAGE_GENS(page));
2465 #endif