tests: Use CHECKED-COMPILE-AND-ASSERT in compiler-2.pure.lisp
[sbcl.git] / src / runtime / marknsweepgc.c
blob7405f036e4a6c0aabdb0c696e1b51f9bbba467ee
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 "gc-private.h"
51 #include "genesis/gc-tables.h"
52 #include "genesis/vector.h"
53 #include "forwarding-ptr.h"
54 #include "pseudo-atomic.h"
55 #include "var-io.h"
56 #include "marknsweepgc.h"
58 #include <stdlib.h>
59 #include <stdio.h>
61 #define WORDS_PER_PAGE ((int)IMMOBILE_CARD_BYTES/N_WORD_BYTES)
62 #define DOUBLEWORDS_PER_PAGE (WORDS_PER_PAGE/2)
64 // In case of problems while debugging, this is selectable.
65 #define DEFRAGMENT_FIXEDOBJ_SUBSPACE 1
67 #undef DEBUG
68 #undef VERIFY_PAGE_GENS
70 #ifdef DEBUG
71 # define dprintf(arg) fprintf arg
72 FILE * logfile;
73 #else
74 # define dprintf(arg)
75 #endif
77 void defrag_immobile_space(int* components, boolean verbose);
79 unsigned asm_routines_end;
81 // Inclusive bounds on highest in-use pages per subspace.
82 low_page_index_t max_used_fixedobj_page, max_used_varyobj_page;
84 // This table is for objects fixed in size, as opposed to variable-sized.
85 // (Immobile objects are naturally fixed in placement)
86 struct fixedobj_page *fixedobj_pages;
87 unsigned int* immobile_scav_queue;
88 int immobile_scav_queue_head;
89 // Number of items enqueued; can exceed QCAPACITY on overflow.
90 // If overflowed, the queue is unusable until reset.
91 unsigned int immobile_scav_queue_count;
92 #define QCAPACITY (IMMOBILE_CARD_BYTES/sizeof(int))
94 #define gens attr.parts.gens_
96 // These are the high 2 bits of 'flags'
97 #define WRITE_PROTECT 0x80
98 #define WRITE_PROTECT_CLEARED 0x40
100 // Packing and unpacking attributes
101 // the low two flag bits are for write-protect status
102 #define MAKE_ATTR(spacing,size,flags) (((spacing)<<8)|((size)<<16)|flags)
103 #define OBJ_SPACING(attr) ((attr>>8) & 0xFF)
105 // Ignore the write-protect bits and the generations when comparing attributes
106 #define ATTRIBUTES_MATCH_P(page_attr,specified_attr) \
107 ((page_attr & 0xFFFF3F) == specified_attr)
108 #define SET_WP_FLAG(index,flag) \
109 fixedobj_pages[index].attr.parts.flags = (fixedobj_pages[index].attr.parts.flags & 0x3F) | flag
111 #define set_page_full(i) fixedobj_pages[i].free_index = IMMOBILE_CARD_BYTES
112 #define page_full_p(i) (fixedobj_pages[i].free_index >= (int)IMMOBILE_CARD_BYTES)
113 #define fixedobj_page_wp(i) (fixedobj_pages[i].attr.parts.flags & WRITE_PROTECT)
115 /// Variable-length pages:
117 // Array of inverted write-protect flags, 1 bit per page.
118 unsigned int* varyobj_page_touched_bits;
119 static int n_bitmap_elts; // length of array measured in 'int's
121 // Array of offsets backwards in double-lispwords from the page end
122 // to the lowest-addressed object touching the page. This offset can
123 // point to a hole, but we prefer that it not. If the offset is zero,
124 // the page has no object other than possibly a hole resulting
125 // from a freed object.
126 unsigned short* varyobj_page_scan_start_offset;
128 // Array of page generation masks
129 unsigned char* varyobj_page_header_gens;
130 // Holes to be stuffed back into the managed free list.
131 lispobj varyobj_holes;
133 #define VARYOBJ_PAGE_GENS(x) varyobj_page_header_gens[x-FIRST_VARYOBJ_PAGE]
134 #define varyobj_page_touched(x) \
135 ((varyobj_page_touched_bits[(x-FIRST_VARYOBJ_PAGE)/32] >> (x&31)) & 1)
137 #ifdef VERIFY_PAGE_GENS
138 void check_fixedobj_page(low_page_index_t);
139 void check_varyobj_pages();
140 #endif
142 // Object header: generation byte --| |-- widetag
143 // v v
144 // 0xzzzzzzzz GGzzzzww
145 // arbitrary data -------- ---- length in words
147 // There is a hard constraint on NUM_GENERATIONS, which is currently 8.
148 // (0..5=normal, 6=pseudostatic, 7=scratch)
149 // It could be as high as 16 for 32-bit words (wherein scratch=gen15)
150 // or 32 for 64-bits words (wherein scratch=gen31).
151 // In each case, the VISITED flag bit weight would need to be modified.
152 // Shifting a 1 bit left by the contents of the generation byte
153 // must not overflow a register.
155 #ifdef LISP_FEATURE_LITTLE_ENDIAN
156 static inline void assign_generation(lispobj* obj, generation_index_t gen)
158 ((generation_index_t*)obj)[3] = gen;
160 // Turn a grey node black.
161 static inline void set_visited(lispobj* obj)
163 gc_dcheck(__immobile_obj_gen_bits(obj) == new_space);
164 ((generation_index_t*)obj)[3] |= IMMOBILE_OBJ_VISITED_FLAG;
166 #else
167 #error "Need to define assign_generation() for big-endian"
168 #endif
170 static inline void *
171 low_page_address(low_page_index_t page_num)
173 return ((char*)IMMOBILE_SPACE_START + (page_num * IMMOBILE_CARD_BYTES));
176 //// Variable-length utilities
178 /* Calculate the address where the first object touching this page starts. */
179 static inline lispobj*
180 varyobj_scan_start(low_page_index_t page_index)
182 return (lispobj*)((char*)low_page_address(page_index+1)
183 - varyobj_page_scan_start_offset[page_index - FIRST_VARYOBJ_PAGE]
184 * (2 * N_WORD_BYTES));
187 /* Return the generation mask for objects headers on 'page_index'
188 including at most one object that starts before the page but ends on
189 or after it.
190 If the scan start is within the page, i.e. less than DOUBLEWORDS_PER_PAGE
191 (note that the scan start is measured relative to the page end) then
192 we don't need to OR in the generation byte from an extra object,
193 as all headers on the page are accounted for in the page generation mask.
194 Also an empty page (where scan start is zero) avoids looking
195 at the next page's first object by accident via the same test. */
196 unsigned char varyobj_page_gens_augmented(low_page_index_t page_index)
198 return (varyobj_page_scan_start_offset[page_index - FIRST_VARYOBJ_PAGE] <= DOUBLEWORDS_PER_PAGE
199 ? 0 : (1<<__immobile_obj_generation(varyobj_scan_start(page_index))))
200 | VARYOBJ_PAGE_GENS(page_index);
203 //// Fixed-length object allocator
205 /* Return the index of an immobile page that is probably not totally full,
206 starting with 'hint_page' and wrapping around.
207 'attributes' determine an eligible page.
208 *IMMOBILE-SPACE-FREE-POINTER* is updated to point beyond the found page
209 if it previously did not. */
211 static int get_freeish_page(int hint_page, int attributes)
213 int page = hint_page;
214 lispobj *new_free_pointer, *old_free_pointer, *actual_old;
215 int page_attr_packed;
216 unsigned char best_genmask = 0xff;
217 int best_page = -1;
219 // Speed of this could be improved by keeping a linked list of pages
220 // with any space available, headed by a field in the page struct.
221 // This is totally lock-free / wait-free though, so it's really not
222 // too shabby, because it never has to deal with a page-table mutex.
223 do {
224 page_attr_packed = fixedobj_pages[page].attr.packed;
225 if (page_attr_packed == 0)
226 if ((page_attr_packed =
227 __sync_val_compare_and_swap(&fixedobj_pages[page].attr.packed,
228 0, attributes)) == 0) {
229 // Atomically assign MAX(old_free_pointer, new_free_pointer)
230 // into the free pointer.
231 new_free_pointer = low_page_address(page+1);
232 old_free_pointer = immobile_fixedobj_free_pointer;
233 while (new_free_pointer > old_free_pointer) {
234 actual_old =
235 __sync_val_compare_and_swap(&immobile_fixedobj_free_pointer,
236 old_free_pointer,
237 new_free_pointer);
238 if (actual_old == old_free_pointer)
239 break;
240 old_free_pointer = actual_old;
242 return page;
244 if (ATTRIBUTES_MATCH_P(page_attr_packed, attributes)
245 && !page_full_p(page)) {
246 // Try to avoid new objects on pages with any pseudo-static objects,
247 // because then touching the young object forces scanning the page,
248 // which is unfortunate if most things on it were untouched.
249 if (fixedobj_pages[page].gens < (1<<PSEUDO_STATIC_GENERATION)) {
250 // instant win
251 return page;
252 } else if (fixedobj_pages[page].gens < best_genmask) {
253 best_genmask = fixedobj_pages[page].gens;
254 best_page = page;
257 if (++page >= FIRST_VARYOBJ_PAGE) page = 0;
258 } while (page != hint_page);
259 if (best_page >= 0)
260 return best_page;
261 lose("No more immobile pages available");
264 // Unused, but possibly will be for some kind of collision-avoidance scheme
265 // on claiming of new free pages.
266 long immobile_alloc_collisions;
268 /* Beginning at page index *hint, attempt to find space
269 for an object on a page with page_attributes. Write its header word
270 and return a C (native) pointer. The start page MUST have the proper
271 characteristisc, but might be totally full.
273 Precondition: Lisp has established a pseudo-atomic section. */
275 /* There is a slightly different algorithm that would probably be faster
276 than what is currently implemented:
277 - hint should be the address of a word that you try to claim
278 as an object header; it moves from high-to-low instead of low-to-high.
279 It's easier to compute the page base than the last valid object start
280 if there are some wasted words at the end due to page size not being
281 a perfect multiple of object size.
282 - you do a CAS into that word, and either suceed or fail
283 - if you succeed, subtract the object spacing and compare
284 to the page's base address, which can be computed by
285 masking. if the next address is above or equal to the page start,
286 store it in the hint, otherwise mark the page full */
288 lispobj alloc_immobile_obj(int page_attributes, lispobj header, int* hint)
290 int page;
291 lispobj word;
292 char * page_data, * obj_ptr, * next_obj_ptr, * limit, * next_free;
293 int spacing_in_bytes = OBJ_SPACING(page_attributes) << WORD_SHIFT;
295 page = *hint;
296 gc_dcheck(low_page_address(page) < (void*)immobile_fixedobj_free_pointer);
297 do {
298 page_data = low_page_address(page);
299 obj_ptr = page_data + fixedobj_pages[page].free_index;
300 limit = page_data + IMMOBILE_CARD_BYTES - spacing_in_bytes;
301 while (obj_ptr <= limit) {
302 word = *(lispobj*)obj_ptr;
303 next_obj_ptr = obj_ptr + spacing_in_bytes;
304 if (fixnump(word) // a fixnum marks free space
305 && __sync_bool_compare_and_swap((lispobj*)obj_ptr,
306 word, header)) {
307 // The value formerly in the header word was the offset to
308 // the next hole. Use it to update the freelist pointer.
309 // Just slam it in.
310 fixedobj_pages[page].free_index = next_obj_ptr + word - page_data;
311 return (lispobj)obj_ptr;
313 // If some other thread updated the free_index
314 // to a larger value, use that. (See example below)
315 next_free = page_data + fixedobj_pages[page].free_index;
316 obj_ptr = next_free > next_obj_ptr ? next_free : next_obj_ptr;
318 set_page_full(page);
319 page = get_freeish_page(page+1 >= FIRST_VARYOBJ_PAGE ? 0 : page+1,
320 page_attributes);
321 *hint = page;
322 } while (1);
326 Example: Conside the freelist initially pointing to word index 6
327 Threads A, and B, and C each want to claim index 6.
328 - Thread A wins and then is switched out immediately after the CAS.
329 - Thread B fails to claim cell 6, claims cell 12 instead.
330 - Thread C fails to claim a cell and is switched out immediately
331 after the CAS.
332 - Thread B writes the index of the next hole, cell 18 into the
333 page's freelist cell.
334 - Thread A wakes up and writes 12 into the freelist cell.
335 - Thread C wakes up sees 12 for next_offset. 12 is greater than 6,
336 so it sets its next probe location to 12.
337 It fails the fixnump(header) test.
338 - Thread C sees that next_offset is still 12,
339 so it skips by the page's object spacing instead, and will continue
340 to do so until hitting the end of the page.
343 //// The collector
345 void update_immobile_nursery_bits()
347 low_page_index_t page;
348 lispobj fixedobj_free_ptr = (lispobj)immobile_fixedobj_free_pointer;
349 lispobj varyobj_free_ptr = (lispobj)immobile_space_free_pointer;
351 // Find the high water marks for this GC scavenge phase
352 // [avoid passing exactly IMMOBILE_SPACE_END, which has no page index]
353 max_used_fixedobj_page = find_immobile_page_index((void*)(fixedobj_free_ptr-1));
354 max_used_varyobj_page = find_immobile_page_index((void*)(varyobj_free_ptr-1));
356 immobile_scav_queue = (unsigned int*)low_page_address(max_used_varyobj_page+1);
357 gc_assert((IMMOBILE_SPACE_END - (uword_t)immobile_scav_queue) / sizeof(int)
358 >= QCAPACITY);
360 if (ENABLE_PAGE_PROTECTION) {
361 // Unprotect the in-use ranges. Any page could be written during scavenge
362 os_protect((os_vm_address_t)IMMOBILE_SPACE_START,
363 fixedobj_free_ptr - IMMOBILE_SPACE_START,
364 OS_VM_PROT_ALL);
366 // varyobj_free_ptr is typically not page-aligned - only by random chance
367 // might it be. Additionally we need a page beyond that for the re-scan queue.
368 os_vm_address_t limit = (char*)immobile_scav_queue + IMMOBILE_CARD_BYTES;
369 os_protect((os_vm_address_t)(IMMOBILE_VARYOBJ_SUBSPACE_START),
370 limit - (os_vm_address_t)IMMOBILE_VARYOBJ_SUBSPACE_START,
371 OS_VM_PROT_ALL);
374 for (page=0; page <= max_used_fixedobj_page ; ++page) {
375 // any page whose free index changed contains nursery objects
376 if (fixedobj_pages[page].free_index >> WORD_SHIFT !=
377 fixedobj_pages[page].prior_gc_free_word_index)
378 fixedobj_pages[page].gens |= 1;
379 #ifdef VERIFY_PAGE_GENS
380 check_fixedobj_page(page);
381 #endif
383 #ifdef VERIFY_PAGE_GENS
384 check_varyobj_pages();
385 #endif
388 /* Turn a white object grey. Also enqueue the object for re-scan if required */
389 void
390 enliven_immobile_obj(lispobj *ptr, int rescan) // a native pointer
392 if (widetag_of(*ptr) == SIMPLE_FUN_WIDETAG)
393 ptr = fun_code_header(ptr);
394 gc_assert(__immobile_obj_gen_bits(ptr) == from_space);
395 int pointerish = !unboxed_obj_widetag_p(widetag_of(*ptr));
396 assign_generation(ptr, (pointerish ? 0 : IMMOBILE_OBJ_VISITED_FLAG) | new_space);
397 low_page_index_t page_index = find_immobile_page_index(ptr);
399 if (page_index >= FIRST_VARYOBJ_PAGE) {
400 VARYOBJ_PAGE_GENS(page_index) |= 1<<new_space;
401 } else {
402 fixedobj_pages[page_index].gens |= 1<<new_space;
404 // If called from preserve_pointer(), then we haven't scanned immobile
405 // roots yet, so we only need ensure that this object's page's WP bit
406 // is cleared so that the page is not skipped during root scan.
407 if (!rescan) {
408 if (pointerish) {
409 if (page_index >= FIRST_VARYOBJ_PAGE)
410 varyobj_page_touched_bits[(page_index-FIRST_VARYOBJ_PAGE)/32]
411 |= 1 << (page_index & 31);
412 else
413 SET_WP_FLAG(page_index, WRITE_PROTECT_CLEARED);
415 return; // No need to enqueue.
418 // Do nothing if either we don't need to look for pointers in this object,
419 // or the work queue has already overflowed, causing a full scan.
420 if (!pointerish || immobile_scav_queue_count > QCAPACITY) return;
422 // count is either less than or equal to QCAPACITY.
423 // If equal, just bump the count to signify overflow.
424 if (immobile_scav_queue_count < QCAPACITY) {
425 immobile_scav_queue[immobile_scav_queue_head] =
426 (uword_t)ptr & 0xFFFFFFFF; // Drop the high bits
427 immobile_scav_queue_head = (immobile_scav_queue_head + 1) & (QCAPACITY - 1);
429 ++immobile_scav_queue_count;
432 /* If 'addr' points to an immobile object, then make the object
433 live by promotion. But if the object is not in the generation
434 being collected, do nothing */
435 void immobile_space_preserve_pointer(void* addr)
437 low_page_index_t page_index = find_immobile_page_index(addr);
438 if (page_index < 0)
439 return;
441 unsigned char genmask = compacting_p() ? 1<<from_space : 0xff;
442 lispobj* object_start;
443 int valid = 0;
445 if (page_index >= FIRST_VARYOBJ_PAGE) {
446 // Restrict addr to lie below IMMOBILE_SPACE_FREE_POINTER.
447 // This way, if the gens byte is nonzero but there is
448 // a final array acting as filler on the remainder of the
449 // final page, we won't accidentally find that.
450 lispobj* scan_start;
451 valid = addr < (void*)immobile_space_free_pointer
452 && (varyobj_page_gens_augmented(page_index) & genmask)
453 && (scan_start = varyobj_scan_start(page_index)) <= (lispobj*)addr
454 && (object_start = gc_search_space(scan_start, addr)) != 0
455 /* gc_search_space can return filler objects, unlike
456 * search_immobile_space which can not */
457 && !immobile_filler_p(object_start)
458 && (instruction_ptr_p(addr, object_start)
459 || properly_tagged_descriptor_p(addr, object_start));
460 } else if (fixedobj_pages[page_index].gens & genmask) {
461 int obj_spacing = fixedobj_page_obj_align(page_index);
462 int obj_index = ((uword_t)addr & (IMMOBILE_CARD_BYTES-1)) / obj_spacing;
463 dprintf((logfile,"Pointer %p is to immobile page %d, object %d\n",
464 addr, page_index, obj_index));
465 char* page_start_addr = (char*)((uword_t)addr & ~(IMMOBILE_CARD_BYTES-1));
466 object_start = (lispobj*)(page_start_addr + obj_index * obj_spacing);
467 valid = !fixnump(*object_start)
468 && (lispobj*)addr < object_start + fixedobj_page_obj_size(page_index)
469 && (properly_tagged_descriptor_p(addr, object_start)
470 || widetag_of(*object_start) == FUNCALLABLE_INSTANCE_WIDETAG);
472 if (valid && (!compacting_p() ||
473 __immobile_obj_gen_bits(object_start) == from_space)) {
474 dprintf((logfile,"immobile obj @ %p (<- %p) is conservatively live\n",
475 header_addr, addr));
476 if (compacting_p())
477 enliven_immobile_obj(object_start, 0);
478 else
479 gc_mark_obj(compute_lispobj(object_start));
481 #undef GEN_MATCH
484 // Loop over the newly-live objects, scavenging them for pointers.
485 // As with the ordinary gencgc algorithm, this uses almost no stack.
486 static void full_scavenge_immobile_newspace()
488 page_index_t page;
489 unsigned char bit = 1<<new_space;
491 // Fixed-size object pages.
493 for (page = 0; page <= max_used_fixedobj_page; ++page) {
494 if (!(fixedobj_pages[page].gens & bit)) continue;
495 // Skip amount within the loop is in bytes.
496 int obj_spacing = fixedobj_page_obj_align(page);
497 lispobj* obj = low_page_address(page);
498 // Use an inclusive, not exclusive, limit. On pages with dense packing
499 // (i.e. non-LAYOUT), if the object size does not evenly divide the page
500 // size, it is wrong to examine memory at an address which could be
501 // an object start, but for the fact that it runs off the page boundary.
502 // On the other hand, unused words hold 0, so it's kind of ok to read them.
503 lispobj* limit = (lispobj*)((char*)obj +
504 IMMOBILE_CARD_BYTES - obj_spacing);
505 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
506 if (!fixnump(*obj) && __immobile_obj_gen_bits(obj) == new_space) {
507 set_visited(obj);
508 lispobj header = *obj;
509 scavtab[widetag_of(header)](obj, header);
514 // Variable-size object pages
516 page = FIRST_VARYOBJ_PAGE - 1; // Subtract 1 because of pre-increment
517 while (1) {
518 // Find the next page with anything in newspace.
519 do {
520 if (++page > max_used_varyobj_page) return;
521 } while ((VARYOBJ_PAGE_GENS(page) & bit) == 0);
522 lispobj* obj = varyobj_scan_start(page);
523 do {
524 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
525 int n_words;
526 for ( ; obj < limit ; obj += n_words ) {
527 lispobj header = *obj;
528 if (__immobile_obj_gen_bits(obj) == new_space) {
529 set_visited(obj);
530 n_words = scavtab[widetag_of(header)](obj, header);
531 } else {
532 n_words = sizetab[widetag_of(header)](obj);
535 page = find_immobile_page_index(obj);
536 // Bail out if exact absolute end of immobile space was reached.
537 if (page < 0) return;
538 // If 'page' should be scanned, then pick up where we left off,
539 // without recomputing 'obj' but setting a higher 'limit'.
540 } while (VARYOBJ_PAGE_GENS(page) & bit);
544 /// Repeatedly scavenge immobile newspace work queue until we find no more
545 /// reachable objects within. (They might be in dynamic space though).
546 /// If queue overflow already happened, then a worst-case full scan is needed.
547 /// If it didn't, we try to drain the queue, hoping that overflow does
548 /// not happen while doing so.
549 /// The approach taken is more subtle than just dequeuing each item,
550 /// scavenging, and letting the outer 'while' loop take over.
551 /// That would be ok, but could cause more full scans than necessary.
552 /// Instead, since each entry in the queue is useful information
553 /// in the non-overflow condition, perform all the work indicated thereby,
554 /// rather than considering the queue discardable as soon as overflow happens.
555 /// Essentially we just have to capture the valid span of enqueued items,
556 /// because the queue state is inconsistent when 'count' exceeds 'capacity'.
557 void scavenge_immobile_newspace()
559 while (immobile_scav_queue_count) {
560 if (immobile_scav_queue_count > QCAPACITY) {
561 immobile_scav_queue_count = 0;
562 full_scavenge_immobile_newspace();
563 } else {
564 int queue_index_from = (immobile_scav_queue_head - immobile_scav_queue_count)
565 & (QCAPACITY - 1);
566 int queue_index_to = immobile_scav_queue_head;
567 int i = queue_index_from;
568 // The termination condition can't be expressed as an inequality,
569 // since the indices might be reversed due to wraparound.
570 // To express as equality entails forcing at least one iteration
571 // since the ending index might be the starting index.
572 do {
573 lispobj* obj = (lispobj*)(uword_t)immobile_scav_queue[i];
574 i = (1 + i) & (QCAPACITY-1);
575 // Only decrement the count if overflow did not happen.
576 // The first iteration of this loop will decrement for sure,
577 // but subsequent iterations might not.
578 if (immobile_scav_queue_count <= QCAPACITY)
579 --immobile_scav_queue_count;
580 if (!(__immobile_obj_gen_bits(obj) & IMMOBILE_OBJ_VISITED_FLAG)) {
581 set_visited(obj);
582 lispobj header = *obj;
583 scavtab[widetag_of(header)](obj, header);
585 } while (i != queue_index_to);
590 // Return a page >= page_index having potential old->young pointers,
591 // or -1 if there isn't one.
592 static int next_varyobj_root_page(unsigned int page_index,
593 unsigned int end_bitmap_index,
594 unsigned char genmask)
596 unsigned int map_index = (page_index - FIRST_VARYOBJ_PAGE) / 32;
597 if (map_index >= end_bitmap_index) return -1;
598 int bit_index = page_index & 31;
599 // Look only at bits of equal or greater weight than bit_index.
600 unsigned int word = (0xFFFFFFFFU << bit_index) & varyobj_page_touched_bits[map_index];
601 while (1) {
602 if (word) {
603 bit_index = ffs(word) - 1;
604 page_index = FIRST_VARYOBJ_PAGE + map_index * 32 + bit_index;
605 if (varyobj_page_gens_augmented(page_index) & genmask)
606 return page_index;
607 else {
608 word ^= (1<<bit_index);
609 continue;
612 if (++map_index >= end_bitmap_index) return -1;
613 word = varyobj_page_touched_bits[map_index];
617 void
618 scavenge_immobile_roots(generation_index_t min_gen, generation_index_t max_gen)
620 // example: scavenging gens 2..6, the mask of root gens is #b1111100
621 int genmask = ((1 << (max_gen - min_gen + 1)) - 1) << min_gen;
623 low_page_index_t page;
624 for (page = 0; page <= max_used_fixedobj_page ; ++page) {
625 if (fixedobj_page_wp(page) || !(fixedobj_pages[page].gens & genmask))
626 continue;
627 int obj_spacing = fixedobj_page_obj_align(page);
628 lispobj* obj = low_page_address(page);
629 lispobj* limit = (lispobj*)((char*)obj +
630 IMMOBILE_CARD_BYTES - obj_spacing);
631 int gen;
632 // Immobile space can only contain objects with a header word,
633 // no conses, so any fixnum where a header could be is not a live
634 // object.
635 do {
636 if (!fixnump(*obj) && (genmask >> (gen=__immobile_obj_gen_bits(obj)) & 1)) {
637 if (gen == new_space) { set_visited(obj); }
638 lispobj header = *obj;
639 scavtab[widetag_of(header)](obj, header);
641 } while ((obj = (lispobj*)((char*)obj + obj_spacing)) <= limit);
644 // Variable-length object pages
645 unsigned n_varyobj_pages = 1+max_used_varyobj_page-FIRST_VARYOBJ_PAGE;
646 unsigned end_bitmap_index = (n_varyobj_pages+31)/32;
647 page = next_varyobj_root_page(FIRST_VARYOBJ_PAGE, end_bitmap_index, genmask);
648 while (page >= 0) {
649 lispobj* obj = varyobj_scan_start(page);
650 do {
651 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
652 int n_words, gen;
653 for ( ; obj < limit ; obj += n_words ) {
654 lispobj header = *obj;
655 if (genmask >> (gen=__immobile_obj_gen_bits(obj)) & 1) {
656 if (gen == new_space) { set_visited(obj); }
657 n_words = scavtab[widetag_of(header)](obj, header);
658 } else {
659 n_words = sizetab[widetag_of(header)](obj);
662 page = find_immobile_page_index(obj);
663 } while (page > 0
664 && (VARYOBJ_PAGE_GENS(page) & genmask)
665 && varyobj_page_touched(page));
666 page = next_varyobj_root_page(1+page, end_bitmap_index, genmask);
668 scavenge_immobile_newspace();
671 #include "genesis/layout.h"
672 #define LAYOUT_SIZE (sizeof (struct layout)/N_WORD_BYTES)
673 /// First 5 layouts: T, FUNCTION, STRUCTURE-OBJECT, LAYOUT, PACKAGE
674 /// (These #defines ought to be emitted by genesis)
675 #define LAYOUT_OF_LAYOUT ((IMMOBILE_SPACE_START+3*LAYOUT_ALIGN)|INSTANCE_POINTER_LOWTAG)
676 #define LAYOUT_OF_PACKAGE ((IMMOBILE_SPACE_START+4*LAYOUT_ALIGN)|INSTANCE_POINTER_LOWTAG)
678 // As long as Lisp doesn't have any native allocators (vops and whatnot)
679 // it doesn't need to access these values.
680 int layout_page_hint, symbol_page_hint, fdefn_page_hint;
682 // For the three different page characteristics that we need,
683 // claim a page that works for those characteristics.
684 void set_immobile_space_hints()
686 // The allocator doesn't check whether each 'hint' points to an
687 // expected kind of page, so we have to ensure up front that
688 // allocations start on different pages. i.e. You can point to
689 // a totally full page, but you can't point to a wrong page.
690 // It doesn't work to just assign these to consecutive integers
691 // without also updating the page attributes.
693 // Object sizes must be multiples of 2 because the n_words value we pass
694 // to scavenge() is gotten from the page attributes, and scavenge asserts
695 // that the ending address is aligned to a doubleword boundary as expected.
697 // For 32-bit immobile space, LAYOUTs must be 256-byte-aligned so that the
698 // low byte of a pointer contains no information, and a layout pointer can
699 // be stored in the high 3 bytes point of an instance header.
700 // instance-length can be recovered from the layout, and need not be stored
701 // in each instance. Representation change in rev 092af9c078c made
702 // things more difficult, but not impossible.
703 layout_page_hint = get_freeish_page(0, MAKE_ATTR(LAYOUT_ALIGN / N_WORD_BYTES, // spacing
704 ALIGN_UP(LAYOUT_SIZE,2),
705 0));
706 symbol_page_hint = get_freeish_page(0, MAKE_ATTR(ALIGN_UP(SYMBOL_SIZE,2),
707 ALIGN_UP(SYMBOL_SIZE,2),
708 0));
709 fdefn_page_hint = get_freeish_page(0, MAKE_ATTR(ALIGN_UP(FDEFN_SIZE,2),
710 ALIGN_UP(FDEFN_SIZE,2),
711 0));
714 void write_protect_immobile_space()
716 immobile_scav_queue = NULL;
717 immobile_scav_queue_head = 0;
719 set_immobile_space_hints();
721 if (!ENABLE_PAGE_PROTECTION)
722 return;
724 // Now find contiguous ranges of pages that are protectable,
725 // minimizing the number of system calls as much as possible.
726 int i, start = -1, end = -1; // inclusive bounds on page indices
727 for (i = max_used_fixedobj_page ; i >= 0 ; --i) {
728 if (fixedobj_page_wp(i)) {
729 if (end < 0) end = i;
730 start = i;
732 if (end >= 0 && (!fixedobj_page_wp(i) || i == 0)) {
733 os_protect(low_page_address(start),
734 IMMOBILE_CARD_BYTES * (1 + end - start),
735 OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
736 start = end = -1;
739 #define varyobj_page_wp(x) !varyobj_page_touched(x)
740 for (i = max_used_varyobj_page ; i >= FIRST_VARYOBJ_PAGE ; --i) {
741 if (varyobj_page_wp(i)) {
742 if (end < 0) end = i;
743 start = i;
745 if (end >= 0 && (!varyobj_page_wp(i) || i == FIRST_VARYOBJ_PAGE)) {
746 os_protect(low_page_address(start),
747 IMMOBILE_CARD_BYTES * (1 + end - start),
748 OS_VM_PROT_READ|OS_VM_PROT_EXECUTE);
749 start = end = -1;
752 #undef varyobj_page_wp
755 // Scan range between start and end (exclusive) for old-to-young pointers.
756 // 'keep_gen' is the value of the generation byte of objects that were
757 // candidates to become garbage, but remain live after this gc.
758 // It will necessarily have the VISITED flag on.
759 // 'new_gen' is the generation number that those objects will have
760 // after collection, which is either the same generation or one higher,
761 // depending on the 'raise' flag for this GC cycle.
762 static int
763 range_points_to_younger_p(lispobj* obj, lispobj* end,
764 int gen, int keep_gen, int new_gen)
766 #ifdef DEBUG
767 lispobj* __attribute__((unused)) saved_obj = obj, __attribute__((unused)) header = *obj;
768 #endif
769 do {
770 lispobj thing = *obj;
771 if (is_lisp_pointer(thing)) {
772 int to_page = find_page_index((void*)thing),
773 to_gen = 255;
774 if (to_page >= 0) { // points to ordinary dynamic space
775 to_gen = page_table[to_page].gen;
776 if (to_gen == PSEUDO_STATIC_GENERATION+1) // scratch gen
777 to_gen = new_gen; // is actually this
778 } else if (immobile_space_p(thing)) {
779 // Processing the code-entry-points slot of a code component
780 // requires the general variant of immobile_obj_gen_bits
781 // because the pointed-to object is a simple-fun.
782 to_gen = immobile_obj_gen_bits(native_pointer(thing));
783 if (to_gen == keep_gen) // keep gen
784 to_gen = new_gen; // is actually this
786 if (to_gen < gen) {
787 return 1; // yes, points to younger
790 } while (++obj < end);
791 return 0; // no, does not point to younger
794 // Scan a fixed-size object for old-to-young pointers.
795 // Since fixed-size objects are boxed and on known boundaries,
796 // we never start in the middle of random bytes, so the answer is exact.
797 static inline boolean
798 fixedobj_points_to_younger_p(lispobj* obj, int n_words,
799 int gen, int keep_gen, int new_gen)
801 unsigned char widetag = widetag_of(*obj);
802 lispobj __attribute__((unused)) funobj[1], layout[1];
803 lispobj lbitmap;
805 switch (widetag) {
806 case FDEFN_WIDETAG:
807 // the seemingly silly use of an array is because points_to_younger_p()
808 // expects to get address ranges, not individual objects
809 funobj[0] = fdefn_callee_lispobj((struct fdefn*)obj);
810 return range_points_to_younger_p(funobj, funobj+1, gen, keep_gen, new_gen)
811 || range_points_to_younger_p(obj+1, obj+3, gen, keep_gen, new_gen);
812 case INSTANCE_WIDETAG:
813 case FUNCALLABLE_INSTANCE_WIDETAG:
814 layout[0] = instance_layout(obj); // same as above
815 if (range_points_to_younger_p(layout, layout+1, gen, keep_gen, new_gen))
816 return 1;
817 lbitmap = LAYOUT(layout[0])->bitmap;
818 if (lbitmap != make_fixnum(-1)) {
819 gc_assert(fixnump(lbitmap)); // No bignums (yet)
820 sword_t bitmap = fixnum_value(lbitmap);
821 lispobj* where = obj + 1;
822 for ( ; --n_words ; ++where, bitmap >>= 1 )
823 if ((bitmap & 1) != 0 &&
824 range_points_to_younger_p(where, where+1, gen, keep_gen, new_gen))
825 return 1;
826 return 0;
828 // FALLTHROUGH_INTENDED
830 return range_points_to_younger_p(obj+1, obj+n_words, gen, keep_gen, new_gen);
833 static boolean
834 varyobj_points_to_younger_p(lispobj* obj, int gen, int keep_gen, int new_gen,
835 os_vm_address_t page_begin,
836 os_vm_address_t page_end) // upper (exclusive) bound
838 lispobj *begin, *end, word = *obj;
839 unsigned char widetag = widetag_of(word);
840 if (widetag == CODE_HEADER_WIDETAG) { // usual case. Like scav_code_header()
841 for_each_simple_fun(i, function_ptr, (struct code*)obj, 0, {
842 begin = SIMPLE_FUN_SCAV_START(function_ptr);
843 end = begin + SIMPLE_FUN_SCAV_NWORDS(function_ptr);
844 if (page_begin > (os_vm_address_t)begin) begin = (lispobj*)page_begin;
845 if (page_end < (os_vm_address_t)end) end = (lispobj*)page_end;
846 if (end > begin
847 && range_points_to_younger_p(begin, end, gen, keep_gen, new_gen))
848 return 1;
850 begin = obj + 1; // skip the header
851 end = obj + code_header_words(word); // exclusive bound on boxed slots
852 } else if (widetag == SIMPLE_VECTOR_WIDETAG) {
853 sword_t length = fixnum_value(((struct vector *)obj)->length);
854 begin = obj + 2; // skip the header and length
855 end = obj + ALIGN_UP(length + 2, 2);
856 } else if (unboxed_obj_widetag_p(widetag)) {
857 return 0;
858 } else {
859 lose("Unexpected widetag @ %p", obj);
861 // Fallthrough: scan words from begin to end
862 if (page_begin > (os_vm_address_t)begin) begin = (lispobj*)page_begin;
863 if (page_end < (os_vm_address_t)end) end = (lispobj*)page_end;
864 if (end > begin && range_points_to_younger_p(begin, end, gen, keep_gen, new_gen))
865 return 1;
866 return 0;
869 /// The next two functions are analogous to 'update_page_write_prot()'
870 /// but they differ in that they are "precise" - random code bytes that look
871 /// like pointers are not accidentally treated as pointers.
873 // If 'page' does not contain any objects that points to an object
874 // younger than themselves, then return true.
875 // This is called on pages that do not themselves contain objects of
876 // the generation being collected, but might contain pointers
877 // to younger generations, which we detect by a cleared WP status bit.
878 // The bit is cleared on any write, though, even of a non-pointer,
879 // so this unfortunately has to be tested much more often than we'd like.
880 static inline boolean can_wp_fixedobj_page(page_index_t page, int keep_gen, int new_gen)
882 int obj_spacing = fixedobj_page_obj_align(page);
883 int obj_size_words = fixedobj_page_obj_size(page);
884 lispobj* obj = low_page_address(page);
885 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES - obj_spacing);
886 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) )
887 if (!fixnump(*obj) && // an object header
888 fixedobj_points_to_younger_p(obj, obj_size_words,
889 __immobile_obj_generation(obj),
890 keep_gen, new_gen))
891 return 0;
892 return 1;
895 // To scan _only_ 'page' is impossible in general, but we can act like only
896 // one page was scanned by backing up to the first object whose end is on
897 // or after it, and then restricting points_to_younger within the boundaries.
898 // Doing it this way is probably much better than conservatively assuming
899 // that any word satisfying is_lisp_pointer() is a pointer.
900 static inline boolean can_wp_varyobj_page(page_index_t page, int keep_gen, int new_gen)
902 lispobj *begin = (lispobj*)low_page_address(page);
903 lispobj *end = begin + WORDS_PER_PAGE;
904 lispobj *obj = varyobj_scan_start(page);
905 for ( ; obj < end ; obj += sizetab[widetag_of(*obj)](obj) ) {
906 gc_assert(other_immediate_lowtag_p(*obj));
907 if (!immobile_filler_p(obj) &&
908 varyobj_points_to_younger_p(obj,
909 __immobile_obj_generation(obj),
910 keep_gen, new_gen,
911 (os_vm_address_t)begin,
912 (os_vm_address_t)end))
913 return 0;
915 return 1;
919 Sweep immobile space by zeroing the memory of trashed objects
920 and linking them into the freelist.
922 Possible improvements:
923 - If an entire page becomes nothing but holes, we could bzero it
924 instead of object-at-a-time clearing. But it's not known to be
925 so until after the sweep, so it would entail two passes per page,
926 one to mark holes and one to zero them.
927 - And perhaps bzero could be used on ranges of holes, because
928 in that case each hole's pointer to the next hole is zero as well.
931 #define SETUP_GENS() \
932 /* Only care about pages with something in old or new space. */ \
933 int relevant_genmask = (1 << from_space) | (1 << new_space); \
934 /* Objects whose gen byte is 'keep_gen' are alive. */ \
935 int keep_gen = IMMOBILE_OBJ_VISITED_FLAG | new_space; \
936 /* Objects whose gen byte is 'from_space' are trash. */ \
937 int discard_gen = from_space; \
938 /* Moving non-garbage into either 'from_space' or 'from_space+1' */ \
939 generation_index_t new_gen = from_space + (raise!=0)
941 // The new value of the page generation mask is computed as follows:
942 // If 'raise' = 1 then:
943 // Nothing resides in 'from_space', and 'from_space+1' gains new objects
944 // if and only if any objects on the page were retained.
945 // If 'raise' = 0 then:
946 // Nothing resides in the scratch generation, and 'from_space'
947 // has objects if and only if any objects were retained.
948 #define COMPUTE_NEW_MASK(var, old) \
949 int var = old & ~(1<<from_space); \
950 if ( raise ) \
951 var |= 1<<(from_space+1) & any_kept; \
952 else \
953 var = (var & ~(1<<new_space)) | (1<<from_space & any_kept)
955 static void
956 sweep_fixedobj_pages(int raise)
958 char *page_base;
959 lispobj *obj, *limit, *hole;
960 // This will be needed for space accounting.
961 // threads might fail to consume all the space on a page.
962 // By storing in the page table the count of holes that really existed
963 // at the start of the prior GC, and subtracting from that the number
964 // that exist now, we know how much usable space was obtained (per page).
965 int n_holes = 0;
966 int word_idx;
968 SETUP_GENS();
970 low_page_index_t page;
971 for (page = 0; page <= max_used_fixedobj_page; ++page) {
972 // On pages that won't need manipulation of the freelist,
973 // we try to do less work than for pages that need it.
974 if (!(fixedobj_pages[page].gens & relevant_genmask)) {
975 // Scan for old->young pointers, and WP if there are none.
976 if (ENABLE_PAGE_PROTECTION && !fixedobj_page_wp(page)
977 && fixedobj_pages[page].gens > 1
978 && can_wp_fixedobj_page(page, keep_gen, new_gen))
979 SET_WP_FLAG(page, WRITE_PROTECT);
980 continue;
982 int obj_spacing = fixedobj_page_obj_align(page);
983 int obj_size_words = fixedobj_page_obj_size(page);
984 page_base = low_page_address(page);
985 limit = (lispobj*)(page_base + IMMOBILE_CARD_BYTES - obj_spacing);
986 obj = (lispobj*)page_base;
987 hole = NULL;
988 int any_kept = 0; // was anything moved to the kept generation
989 n_holes = 0;
991 // wp_it is 1 if we should try to write-protect it now.
992 // If already write-protected, skip the tests.
993 int wp_it = ENABLE_PAGE_PROTECTION && !fixedobj_page_wp(page);
994 int gen;
995 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
996 if (fixnump(*obj)) { // was already a hole
997 trash_it:
998 // re-link it into the new freelist
999 if (hole)
1000 // store the displacement from the end of the object
1001 // at prev_hole to the start of this object.
1002 *hole = (lispobj)((char*)obj - ((char*)hole + obj_spacing));
1003 else // this is the first seen hole on the page
1004 // record the byte offset to that hole
1005 fixedobj_pages[page].free_index = (char*)obj - page_base;
1006 hole = obj;
1007 n_holes ++;
1008 } else if ((gen = __immobile_obj_gen_bits(obj)) == discard_gen) { // trash
1009 for (word_idx=obj_size_words-1 ; word_idx > 0 ; --word_idx)
1010 obj[word_idx] = 0;
1011 goto trash_it;
1012 } else if (gen == keep_gen) {
1013 assign_generation(obj, gen = new_gen);
1014 #ifdef DEBUG
1015 gc_assert(!fixedobj_points_to_younger_p(obj, obj_size_words,
1016 gen, keep_gen, new_gen));
1017 #endif
1018 any_kept = -1;
1019 } else if (wp_it && fixedobj_points_to_younger_p(obj, obj_size_words,
1020 gen, keep_gen, new_gen))
1021 wp_it = 0;
1023 if ( hole ) // terminate the chain of holes
1024 *hole = (lispobj)((char*)obj - ((char*)hole + obj_spacing));
1025 fixedobj_pages[page].prior_gc_free_word_index =
1026 fixedobj_pages[page].free_index >> WORD_SHIFT;
1028 COMPUTE_NEW_MASK(mask, fixedobj_pages[page].gens);
1029 if ( mask ) {
1030 fixedobj_pages[page].gens = mask;
1031 if (wp_it) {
1032 SET_WP_FLAG(page, WRITE_PROTECT);
1033 dprintf((logfile, "Lowspace: set WP on page %d\n", page));
1035 } else {
1036 dprintf((logfile,"page %d is all garbage\n", page));
1037 fixedobj_pages[page].attr.packed = 0;
1039 #ifdef DEBUG
1040 check_fixedobj_page(page);
1041 #endif
1042 dprintf((logfile,"page %d: %d holes\n", page, n_holes));
1046 void verify_immobile_page_protection(int,int);
1048 // Scan for freshly trashed objects and turn them into filler.
1049 // Lisp is responsible for consuming the free space
1050 // when it next allocates a variable-size object.
1051 static void
1052 sweep_varyobj_pages(int raise)
1054 SETUP_GENS();
1056 lispobj* free_pointer = immobile_space_free_pointer;
1057 low_page_index_t page;
1058 for (page = FIRST_VARYOBJ_PAGE; page <= max_used_varyobj_page; ++page) {
1059 int genmask = VARYOBJ_PAGE_GENS(page);
1060 if (!(genmask & relevant_genmask)) { // Has nothing in oldspace or newspace.
1061 // Scan for old->young pointers, and WP if there are none.
1062 if (ENABLE_PAGE_PROTECTION && varyobj_page_touched(page)
1063 && varyobj_page_gens_augmented(page) > 1
1064 && can_wp_varyobj_page(page, keep_gen, new_gen))
1065 varyobj_page_touched_bits[(page - FIRST_VARYOBJ_PAGE)/32] &= ~(1<<(page & 31));
1066 continue;
1068 lispobj* page_base = (lispobj*)low_page_address(page);
1069 lispobj* limit = page_base + WORDS_PER_PAGE;
1070 if (limit > free_pointer) limit = free_pointer;
1071 int any_kept = 0; // was anything moved to the kept generation
1072 // wp_it is 1 if we should try to write-protect it now.
1073 // If already write-protected, skip the tests.
1074 int wp_it = ENABLE_PAGE_PROTECTION && varyobj_page_touched(page);
1075 lispobj* obj = varyobj_scan_start(page);
1076 int size, gen;
1078 if (obj < page_base) {
1079 // An object whose tail is on this page, or which spans this page,
1080 // would have been promoted/kept while dealing with the page with
1081 // the object header. Therefore we don't need to consider that object,
1082 // * except * that we do need to consider whether it is an old object
1083 // pointing to a young object.
1084 if (wp_it // If we wanted to try write-protecting this page,
1085 // and the object starting before this page is strictly older
1086 // than the generation that we're moving retained objects into
1087 && (gen = __immobile_obj_gen_bits(obj)) > new_gen
1088 // and it contains an old->young pointer
1089 && varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1090 (os_vm_address_t)page_base,
1091 (os_vm_address_t)limit)) {
1092 wp_it = 0;
1094 // We MUST skip this object in the sweep, because in the case of
1095 // non-promotion (raise=0), we could see an object in from_space
1096 // and believe it to be dead.
1097 obj += sizetab[widetag_of(*obj)](obj);
1098 // obj can't hop over this page. If it did, there would be no
1099 // headers on the page, and genmask would have been zero.
1100 gc_assert(obj < limit);
1102 for ( ; obj < limit ; obj += size ) {
1103 lispobj word = *obj;
1104 size = sizetab[widetag_of(word)](obj);
1105 if (immobile_filler_p(obj)) { // do nothing
1106 } else if ((gen = __immobile_obj_gen_bits(obj)) == discard_gen) {
1107 if (size < 4)
1108 lose("immobile object @ %p too small to free", obj);
1109 else { // Create a filler object.
1110 struct code* code = (struct code*)obj;
1111 code->header = 2<<N_WIDETAG_BITS | CODE_HEADER_WIDETAG;
1112 code->code_size = make_fixnum((size - 2) * N_WORD_BYTES);
1113 code->debug_info = varyobj_holes;
1114 varyobj_holes = (lispobj)code;
1116 } else if (gen == keep_gen) {
1117 assign_generation(obj, gen = new_gen);
1118 #ifdef DEBUG
1119 gc_assert(!varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1120 (os_vm_address_t)page_base,
1121 (os_vm_address_t)limit));
1122 #endif
1123 any_kept = -1;
1124 } else if (wp_it &&
1125 varyobj_points_to_younger_p(obj, gen, keep_gen, new_gen,
1126 (os_vm_address_t)page_base,
1127 (os_vm_address_t)limit))
1128 wp_it = 0;
1130 COMPUTE_NEW_MASK(mask, VARYOBJ_PAGE_GENS(page));
1131 VARYOBJ_PAGE_GENS(page) = mask;
1132 if ( mask && wp_it )
1133 varyobj_page_touched_bits[(page - FIRST_VARYOBJ_PAGE)/32] &= ~(1 << (page & 31));
1135 #ifdef DEBUG
1136 verify_immobile_page_protection(keep_gen, new_gen);
1137 #endif
1140 static void compute_immobile_space_bound()
1142 int max;
1143 // find the highest page in use
1144 for (max = FIRST_VARYOBJ_PAGE-1 ; max >= 0 ; --max)
1145 if (fixedobj_pages[max].attr.parts.obj_size)
1146 break;
1147 max_used_fixedobj_page = max; // this is a page index, not the number of pages.
1148 immobile_fixedobj_free_pointer =
1149 (lispobj*)(IMMOBILE_SPACE_START + IMMOBILE_CARD_BYTES*(1+max));
1151 for (max = (IMMOBILE_SPACE_SIZE/IMMOBILE_CARD_BYTES)-1 ;
1152 max >= FIRST_VARYOBJ_PAGE ; --max)
1153 if (varyobj_page_gens_augmented(max))
1154 break;
1155 max_used_varyobj_page = max; // this is a page index, not the number of pages.
1158 // TODO: (Maybe this won't work. Not sure yet.) rather than use the
1159 // same 'raise' concept as in gencgc, each immobile object can store bits
1160 // indicating whether it has survived any GC at its current generation.
1161 // If it has, then it gets promoted next time, rather than all or nothing
1162 // being promoted from the generation getting collected.
1163 void
1164 sweep_immobile_space(int raise)
1166 gc_assert(immobile_scav_queue_count == 0);
1167 sweep_fixedobj_pages(raise);
1168 sweep_varyobj_pages(raise);
1169 compute_immobile_space_bound();
1172 static void gc_init_immobile()
1174 #ifdef DEBUG
1175 logfile = stderr;
1176 #endif
1177 int n_fixedobj_pages = FIRST_VARYOBJ_PAGE;
1178 int n_varyobj_pages = (IMMOBILE_SPACE_SIZE - IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE)
1179 / IMMOBILE_CARD_BYTES;
1180 fixedobj_pages = calloc(n_fixedobj_pages, sizeof(struct fixedobj_page));
1181 gc_assert(fixedobj_pages);
1183 n_bitmap_elts = (n_varyobj_pages + 31) / 32;
1184 int request = n_bitmap_elts * sizeof (int)
1185 + n_varyobj_pages * (sizeof (short)+sizeof (char));
1186 char* varyobj_page_tables = calloc(1, request);
1187 gc_assert(varyobj_page_tables);
1188 varyobj_page_touched_bits = (unsigned int*)varyobj_page_tables;
1189 // The conservative value for 'touched' is 1.
1190 memset(varyobj_page_touched_bits, 0xff, n_bitmap_elts * sizeof (int));
1191 varyobj_page_scan_start_offset = (unsigned short*)(varyobj_page_touched_bits + n_bitmap_elts);
1192 varyobj_page_header_gens = (unsigned char*)(varyobj_page_scan_start_offset + n_varyobj_pages);
1195 /* Because the immobile page table is not dumped into a core image,
1196 we have to reverse-engineer the characteristics of each page,
1197 which means figuring out what the object spacing should be.
1198 This is not difficult, but is a bit of a kludge */
1200 static inline int immobile_obj_spacing(lispobj header_word, lispobj *obj,
1201 int actual_size)
1203 if (widetag_of(header_word) == INSTANCE_WIDETAG &&
1204 instance_layout(obj) == LAYOUT_OF_LAYOUT)
1205 return LAYOUT_ALIGN / N_WORD_BYTES;
1206 else
1207 return actual_size; // in words
1210 // Signify that scan_start is initially not reliable
1211 static int page_attributes_valid;
1213 // Set the characteristics of each used page at image startup time.
1214 void immobile_space_coreparse(uword_t fixedobj_len, uword_t varyobj_len)
1216 int n_pages, word_idx, page;
1217 uword_t address;
1219 gc_init_immobile();
1221 address = IMMOBILE_SPACE_START;
1222 n_pages = fixedobj_len / IMMOBILE_CARD_BYTES;
1223 for (page = 0 ; page < n_pages ; ++page) {
1224 lispobj* page_data = low_page_address(page);
1225 for (word_idx = 0 ; word_idx < WORDS_PER_PAGE ; ++word_idx) {
1226 lispobj* obj = page_data + word_idx;
1227 lispobj header = *obj;
1228 if (!fixnump(header)) {
1229 gc_assert(other_immediate_lowtag_p(*obj));
1230 int size = sizetab[widetag_of(header)](obj);
1231 fixedobj_pages[page].attr.parts.obj_size = size;
1232 fixedobj_pages[page].attr.parts.obj_align
1233 = immobile_obj_spacing(header, obj, size);
1234 fixedobj_pages[page].gens |= 1 << __immobile_obj_gen_bits(obj);
1235 if (ENABLE_PAGE_PROTECTION)
1236 fixedobj_pages[page].attr.parts.flags = WRITE_PROTECT;
1237 break;
1241 address = IMMOBILE_VARYOBJ_SUBSPACE_START;
1242 n_pages = varyobj_len / IMMOBILE_CARD_BYTES;
1243 lispobj* obj = (lispobj*)address;
1244 int n_words;
1245 low_page_index_t last_page = 0;
1246 // coreparse() already set immobile_space_free_pointer
1247 lispobj* limit = immobile_space_free_pointer;
1248 gc_assert(limit != 0 /* would be zero if not mmapped yet */
1249 && limit <= (lispobj*)(address + varyobj_len));
1250 for ( ; obj < limit ; obj += n_words ) {
1251 gc_assert(other_immediate_lowtag_p(obj[0]));
1252 n_words = sizetab[widetag_of(*obj)](obj);
1253 if (immobile_filler_p(obj)) {
1254 // Holes were chained through the debug_info slot at save.
1255 // Just update the head of the chain.
1256 varyobj_holes = (lispobj)obj;
1257 continue;
1259 low_page_index_t first_page = find_immobile_page_index(obj);
1260 last_page = find_immobile_page_index(obj+n_words-1);
1261 // Only the page with this object header gets a bit in its gen mask.
1262 VARYOBJ_PAGE_GENS(first_page) |= 1<<__immobile_obj_gen_bits(obj);
1263 // For each page touched by this object, set the page's
1264 // scan_start_offset, unless it was already set.
1265 int page;
1266 for (page = first_page ; page <= last_page ; ++page) {
1267 if (!varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE]) {
1268 long offset = (char*)low_page_address(page+1) - (char*)obj;
1269 varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE]
1270 = offset >> (WORD_SHIFT + 1);
1274 // Write a padding object if necessary
1275 if ((uword_t)limit & (IMMOBILE_CARD_BYTES-1)) {
1276 int remainder = IMMOBILE_CARD_BYTES -
1277 ((uword_t)limit & (IMMOBILE_CARD_BYTES-1));
1278 limit[0] = SIMPLE_ARRAY_FIXNUM_WIDETAG;
1279 limit[1] = make_fixnum((remainder >> WORD_SHIFT) - 2);
1280 int size = sizetab[SIMPLE_ARRAY_FIXNUM_WIDETAG](limit);
1281 lispobj* __attribute__((unused)) padded_end = limit + size;
1282 gc_assert(!((uword_t)padded_end & (IMMOBILE_CARD_BYTES-1)));
1284 // Write-protect the pages occupied by the core file.
1285 // (There can be no inter-generation pointers.)
1286 if (ENABLE_PAGE_PROTECTION) {
1287 int page;
1288 for (page = FIRST_VARYOBJ_PAGE ; page <= last_page ; ++page)
1289 varyobj_page_touched_bits[(page-FIRST_VARYOBJ_PAGE)/32] &= ~(1<<(page & 31));
1291 compute_immobile_space_bound();
1292 struct code* code = (struct code*)address;
1293 while (!code_n_funs(code)) {
1294 gc_assert(widetag_of(code->header) == CODE_HEADER_WIDETAG);
1295 code = (struct code*)
1296 (lispobj*)code + sizetab[CODE_HEADER_WIDETAG]((lispobj*)code);
1298 asm_routines_end = (unsigned)(uword_t)code;
1299 page_attributes_valid = 1;
1302 // Demote pseudo-static to highest normal generation
1303 // so that all objects become eligible for collection.
1304 void prepare_immobile_space_for_final_gc()
1306 int page;
1307 char* page_base;
1308 char* page_end = (char*)immobile_fixedobj_free_pointer;
1310 // The list of holes need not be saved.
1311 SYMBOL(IMMOBILE_FREELIST)->value = NIL;
1313 for (page_base = (char*)IMMOBILE_SPACE_START, page = 0 ;
1314 page_base < page_end ;
1315 page_base += IMMOBILE_CARD_BYTES, ++page) {
1316 unsigned char mask = fixedobj_pages[page].gens;
1317 if (mask & 1<<PSEUDO_STATIC_GENERATION) {
1318 int obj_spacing = fixedobj_page_obj_align(page);
1319 lispobj* obj = (lispobj*)page_base;
1320 lispobj* limit = (lispobj*)(page_base + IMMOBILE_CARD_BYTES - obj_spacing);
1321 for ( ; obj <= limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1322 if (!fixnump(*obj)
1323 && __immobile_obj_gen_bits(obj) == PSEUDO_STATIC_GENERATION)
1324 assign_generation(obj, HIGHEST_NORMAL_GENERATION);
1326 fixedobj_pages[page].gens = (mask & ~(1<<PSEUDO_STATIC_GENERATION))
1327 | 1<<HIGHEST_NORMAL_GENERATION;
1331 lispobj* obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1332 lispobj* limit = immobile_space_free_pointer;
1333 for ( ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
1334 if (__immobile_obj_gen_bits(obj) == PSEUDO_STATIC_GENERATION)
1335 assign_generation(obj, HIGHEST_NORMAL_GENERATION);
1337 int max_page = find_immobile_page_index(limit-1);
1338 for ( page = FIRST_VARYOBJ_PAGE ; page <= max_page ; ++page ) {
1339 int mask = VARYOBJ_PAGE_GENS(page);
1340 if (mask & (1<<PSEUDO_STATIC_GENERATION)) {
1341 VARYOBJ_PAGE_GENS(page) = (mask & ~(1<<PSEUDO_STATIC_GENERATION))
1342 | 1<<HIGHEST_NORMAL_GENERATION;
1347 int* code_component_order;
1349 // Now once again promote all objects to pseudo-static just prior to save.
1350 // 'coreparse' makes all pages in regular dynamic space pseudo-static.
1351 // But since immobile objects store their generation, it must be done at save,
1352 // or else it would have to be done on image restart
1353 // which would require writing to a lot of pages for no reason.
1354 void prepare_immobile_space_for_save(lispobj init_function, boolean verbose)
1356 // Don't use the page attributes now - defrag doesn't update them.
1357 lispobj* obj = (lispobj*)IMMOBILE_SPACE_START;
1358 lispobj* limit = immobile_fixedobj_free_pointer;
1359 while (obj < limit) {
1360 if (other_immediate_lowtag_p(*obj))
1361 assign_generation(obj, PSEUDO_STATIC_GENERATION);
1362 obj += sizetab[widetag_of(*obj)](obj);
1365 obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1366 limit = immobile_space_free_pointer;
1367 for ( varyobj_holes = 0 ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
1368 if (immobile_filler_p(obj)) {
1369 struct code* code = (struct code*)obj;
1370 code->debug_info = varyobj_holes;
1371 varyobj_holes = (lispobj)code;
1372 // 0-fill the unused space.
1373 int nwords = sizetab[widetag_of(*obj)](obj);
1374 memset(code->constants, 0,
1375 (nwords * N_WORD_BYTES) - offsetof(struct code, constants));
1376 } else
1377 assign_generation(obj, PSEUDO_STATIC_GENERATION);
1380 // It's better to wait to defrag until after the binding stack is undone,
1381 // because we explicitly don't fixup code refs from stacks.
1382 // i.e. if there *were* something on the binding stack that cared that code
1383 // moved, it would be wrong. This way we can be sure we don't care.
1384 if (code_component_order) {
1385 // Assert that defrag will not move the init_function
1386 gc_assert(!immobile_space_p(init_function));
1387 if (verbose) {
1388 printf("[defragmenting immobile space... ");
1389 fflush(stdout);
1391 defrag_immobile_space(code_component_order, verbose);
1392 if (verbose) printf("done]\n");
1396 //// Interface
1398 int immobile_space_handle_wp_violation(void* fault_addr)
1400 low_page_index_t page_index = find_immobile_page_index(fault_addr);
1401 if (page_index < 0) return 0;
1403 os_protect((os_vm_address_t)((lispobj)fault_addr & ~(IMMOBILE_CARD_BYTES-1)),
1404 IMMOBILE_CARD_BYTES, OS_VM_PROT_ALL);
1405 if (page_index >= FIRST_VARYOBJ_PAGE) {
1406 // The free pointer can move up or down. Attempting to insist that a WP
1407 // fault not occur above the free pointer (plus some slack) is not
1408 // threadsafe, so allow it anywhere. More strictness could be imparted
1409 // by tracking the max value attained by the free pointer.
1410 __sync_or_and_fetch(&varyobj_page_touched_bits[(page_index-FIRST_VARYOBJ_PAGE)/32],
1411 1 << (page_index & 31));
1412 } else {
1413 // FIXME: a single bitmap of touched bits would make more sense,
1414 // and the _CLEARED flag doesn't achieve much if anything.
1415 if (!(fixedobj_pages[page_index].attr.parts.flags
1416 & (WRITE_PROTECT|WRITE_PROTECT_CLEARED)))
1417 return 0;
1418 SET_WP_FLAG(page_index, WRITE_PROTECT_CLEARED);
1420 return 1;
1423 // Find the object that encloses pointer.
1424 lispobj *
1425 search_immobile_space(void *pointer)
1427 lispobj *start;
1429 if ((lispobj)pointer >= IMMOBILE_SPACE_START
1430 && pointer < (void*)immobile_space_free_pointer) {
1431 low_page_index_t page_index = find_immobile_page_index(pointer);
1432 if ((lispobj)pointer >= IMMOBILE_VARYOBJ_SUBSPACE_START) {
1433 if (page_attributes_valid) {
1434 start = (lispobj*)varyobj_scan_start(page_index);
1435 if (start > (lispobj*)pointer) return NULL;
1436 } else {
1437 start = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1439 lispobj* found = gc_search_space(start, pointer);
1440 return (found && immobile_filler_p(found)) ? 0 : found;
1441 } else if (pointer < (void*)immobile_fixedobj_free_pointer) {
1442 char *page_base = (char*)((lispobj)pointer & ~(IMMOBILE_CARD_BYTES-1));
1443 if (page_attributes_valid) {
1444 int spacing = fixedobj_page_obj_align(page_index);
1445 int index = ((char*)pointer - page_base) / spacing;
1446 char *begin = page_base + spacing * index;
1447 char *end = begin + (fixedobj_page_obj_size(page_index) << WORD_SHIFT);
1448 if ((char*)pointer < end) return (lispobj*)begin;
1449 } else {
1450 return gc_search_space((lispobj*)page_base, pointer);
1454 return NULL;
1457 // For coalescing holes, we need to scan backwards, which is done by
1458 // looking backwards for a page that contains the start of a
1459 // block of objects one of which must abut 'obj'.
1460 lispobj* find_preceding_object(lispobj* obj)
1462 int page = find_immobile_page_index(obj);
1463 while (1) {
1464 int offset = varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE];
1465 if (offset) { // 0 means the page is empty.
1466 lispobj* start = varyobj_scan_start(page);
1467 if (start < obj) { // Scan from here forward
1468 while (1) {
1469 lispobj* end = start + sizetab[widetag_of(*start)](start);
1470 if (end == obj) return start;
1471 gc_assert(end < obj);
1472 start = end;
1476 if (page == FIRST_VARYOBJ_PAGE) {
1477 gc_assert(obj == low_page_address(FIRST_VARYOBJ_PAGE));
1478 return 0; // Predecessor does not exist
1480 --page;
1484 #include "genesis/vector.h"
1485 #include "genesis/instance.h"
1486 lispobj alloc_layout(lispobj slots)
1488 struct vector* v = VECTOR(slots);
1489 // If INSTANCE_DATA_START is 0, subtract 1 word for the header.
1490 // If 1, subtract 2 words: 1 for the header and 1 for the layout.
1491 if (v->length != make_fixnum(LAYOUT_SIZE - INSTANCE_DATA_START - 1))
1492 lose("bad arguments to alloc_layout");
1493 struct instance* l = (struct instance*)
1494 alloc_immobile_obj(MAKE_ATTR(LAYOUT_ALIGN / N_WORD_BYTES,
1495 ALIGN_UP(LAYOUT_SIZE,2),
1497 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1498 (LAYOUT_OF_LAYOUT << 32) |
1499 #endif
1500 (LAYOUT_SIZE-1)<<8 | INSTANCE_WIDETAG,
1501 &layout_page_hint);
1502 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1503 l->slots[0] = LAYOUT_OF_LAYOUT;
1504 #endif
1505 memcpy(&l->slots[INSTANCE_DATA_START], v->data,
1506 (LAYOUT_SIZE - INSTANCE_DATA_START - 1)*N_WORD_BYTES);
1508 // Possible efficiency win: make the "wasted" bytes after the layout into a
1509 // simple unboxed array so that heap-walking can skip in one step.
1510 // Probably only a performance issue for MAP-ALLOCATED-OBJECTS,
1511 // since scavenging know to skip by the object alignment anyway.
1512 return make_lispobj(l, INSTANCE_POINTER_LOWTAG);
1515 #include "genesis/symbol.h"
1516 lispobj alloc_sym(lispobj name)
1518 // While there are different "kinds" of symbols in the defragmentation
1519 // logic, we don't distinguish them when allocating,
1520 // on the theory that contiguous allocations are preferable anyway.
1521 struct symbol* s = (struct symbol*)
1522 alloc_immobile_obj(MAKE_ATTR(ALIGN_UP(SYMBOL_SIZE,2), // spacing
1523 ALIGN_UP(SYMBOL_SIZE,2), // size
1525 (SYMBOL_SIZE-1)<<8 | SYMBOL_WIDETAG,
1526 &symbol_page_hint);
1527 s->value = UNBOUND_MARKER_WIDETAG;
1528 s->hash = 0;
1529 s->info = NIL;
1530 s->name = name;
1531 s->package = NIL;
1532 return make_lispobj(s, OTHER_POINTER_LOWTAG);
1535 #include "genesis/fdefn.h"
1536 lispobj alloc_fdefn(lispobj name)
1538 struct fdefn* f = (struct fdefn*)
1539 alloc_immobile_obj(MAKE_ATTR(ALIGN_UP(FDEFN_SIZE,2), // spacing
1540 ALIGN_UP(FDEFN_SIZE,2), // size
1542 (FDEFN_SIZE-1)<<8 | FDEFN_WIDETAG,
1543 &fdefn_page_hint);
1544 f->name = name;
1545 f->fun = NIL;
1546 f->raw_addr = 0;
1547 return make_lispobj(f, OTHER_POINTER_LOWTAG);
1550 #if defined(LISP_FEATURE_IMMOBILE_CODE) && defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER)
1551 #include "genesis/funcallable-instance.h"
1552 #define GF_SIZE (sizeof(struct funcallable_instance)/sizeof(lispobj)+2) /* = 6 */
1553 lispobj alloc_generic_function(lispobj slots)
1555 // GFs have no C header file to represent the layout, which is 6 words:
1556 // header, entry-point, fin-function, slots, raw data (x2)
1557 lispobj* obj = (lispobj*)
1558 alloc_immobile_obj(MAKE_ATTR(ALIGN_UP(GF_SIZE,2), // spacing
1559 ALIGN_UP(GF_SIZE,2), // size
1561 // 5 payload words following the header
1562 ((GF_SIZE-1)<<8) | FUNCALLABLE_INSTANCE_WIDETAG,
1563 // KLUDGE: same page attributes as symbols,
1564 // so use the same hint.
1565 &symbol_page_hint);
1566 ((struct funcallable_instance*)obj)->info[0] = slots;
1567 ((struct funcallable_instance*)obj)->trampoline = (lispobj)(obj + 4);
1568 return make_lispobj(obj, FUN_POINTER_LOWTAG);
1570 #endif
1572 #ifdef LISP_FEATURE_IMMOBILE_CODE
1573 //// Defragmentation
1575 static struct {
1576 char* start;
1577 int n_bytes;
1578 } fixedobj_tempspace, varyobj_tempspace;
1580 // Given an adddress in the target core, return the equivalent
1581 // physical address to read or write during defragmentation
1582 static lispobj* tempspace_addr(void* address)
1584 int byte_index = (char*)address - (char*)IMMOBILE_VARYOBJ_SUBSPACE_START;
1585 gc_assert(immobile_space_p((lispobj)address));
1586 if (byte_index < 0) { // fixedobj subspace
1587 if (fixedobj_tempspace.n_bytes == 0) return address;
1588 byte_index = (char*)address - (char*)IMMOBILE_SPACE_START;
1589 gc_assert(byte_index < fixedobj_tempspace.n_bytes);
1590 return (void*)(fixedobj_tempspace.start + byte_index);
1591 } else { // varyobj subspace
1592 gc_assert(byte_index < varyobj_tempspace.n_bytes);
1593 return (void*)(varyobj_tempspace.start + byte_index);
1597 /* Search for an object during defragmentation */
1598 static lispobj* defrag_search_varyobj_subspace(lispobj addr)
1600 low_page_index_t page = find_immobile_page_index((void*)(long)addr);
1601 lispobj *where = varyobj_scan_start(page);
1602 size_t count;
1603 do {
1604 if (immobile_filler_p(where)) {
1605 count = sizetab[widetag_of(*where)](where);
1606 } else {
1607 gc_assert(forwarding_pointer_p(where));
1608 lispobj *forwarded_obj = native_pointer(forwarding_pointer_value(where));
1609 lispobj *temp_obj = tempspace_addr(forwarded_obj);
1610 count = sizetab[widetag_of(*temp_obj)](temp_obj);
1611 if ((lispobj*)(uword_t)addr < where+count) {
1612 int __attribute__((unused)) widetag = widetag_of(*temp_obj);
1613 gc_assert(widetag == CODE_HEADER_WIDETAG ||
1614 widetag == FDEFN_WIDETAG ||
1615 widetag == FUNCALLABLE_INSTANCE_WIDETAG);
1616 return where;
1619 } while ((where += count) <= (lispobj*)(uword_t)addr);
1620 lose("Can't find jump target");
1623 static void adjust_words(lispobj *where, sword_t n_words, uword_t arg)
1625 int i;
1626 for (i=0;i<n_words;++i) {
1627 lispobj ptr = where[i];
1628 if (is_lisp_pointer(ptr) && forwarding_pointer_p(native_pointer(ptr)))
1629 where[i] = forwarding_pointer_value(native_pointer(ptr));
1633 static lispobj adjust_fun_entrypoint(lispobj raw_addr)
1635 // closure tramp and fin tramp don't have a simple-fun header.
1636 // Do not examine the word where the header would be,
1637 // since it could confuse adjust_words() by having a bit pattern
1638 // resembling a FP. (It doesn't, but better safe than sorry)
1639 if (raw_addr < asm_routines_end) return raw_addr;
1640 lispobj simple_fun = raw_addr - FUN_RAW_ADDR_OFFSET;
1641 adjust_words(&simple_fun, 1, 0);
1642 return simple_fun + FUN_RAW_ADDR_OFFSET;
1645 /// Fixup the fdefn at 'where' based on it moving by 'displacement'.
1646 /// 'fdefn_old' is needed for computing the pre-fixup callee if the
1647 /// architecture uses a call-relative instruction.
1648 static void adjust_fdefn_entrypoint(lispobj* where, int displacement,
1649 struct fdefn* fdefn_old)
1651 struct fdefn* fdefn = (struct fdefn*)where;
1652 int callee_adjust = 0;
1653 // Get the tagged object referred to by the fdefn_raw_addr.
1654 lispobj callee_old = fdefn_callee_lispobj(fdefn_old);
1655 // If it's the undefined function trampoline, or the referent
1656 // did not move, then the callee_adjust stays 0.
1657 // Otherwise we adjust the rel32 field by the change in callee address.
1658 if (callee_old && forwarding_pointer_p(native_pointer(callee_old))) {
1659 lispobj callee_new = forwarding_pointer_value(native_pointer(callee_old));
1660 callee_adjust = callee_new - callee_old;
1662 #ifdef LISP_FEATURE_X86_64
1663 *(int*)((char*)&fdefn->raw_addr + 1) += callee_adjust - displacement;
1664 #else
1665 #error "Can't adjust fdefn_raw_addr for this architecture"
1666 #endif
1669 /* Fix the layout of OBJ, and return the layout's address in tempspace.
1670 * If compact headers, store the layout back into the object.
1671 * If non-compact headers, DO NOT store the layout back into the object,
1672 * because that will be done when instance_scan() touches all slots.
1673 * If it were wrongly done now, then the following (real example) happens:
1674 * instance @ 0x1000000000 has layout pointer 0x203cb483.
1675 * layout @ 0x203cb483 forwards to 0x2030c483.
1676 * object _currently_ at 0x2030c480 (NOT a layout) forwards to 0x203c39cf.
1677 * so the instance winds up with a non-layout in its layout after
1678 * instance_scan() forwards that slot "again". */
1679 static struct layout* fix_object_layout(lispobj* obj)
1681 // This works on instances, funcallable instances (and/or closures)
1682 // but the latter only if the layout is in the header word.
1683 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1684 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG
1685 || widetag_of(*obj) == FUNCALLABLE_INSTANCE_WIDETAG
1686 || widetag_of(*obj) == CLOSURE_WIDETAG);
1687 #else
1688 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1689 #endif
1690 lispobj layout = instance_layout(obj);
1691 if (layout == 0) return 0;
1692 if (forwarding_pointer_p(native_pointer(layout))) { // usually
1693 layout = forwarding_pointer_value(native_pointer(layout));
1694 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1695 instance_layout(obj) = layout;
1696 #endif
1698 struct layout* native_layout = (struct layout*)tempspace_addr(LAYOUT(layout));
1699 gc_assert(widetag_of(native_layout->header) == INSTANCE_WIDETAG);
1700 gc_assert(instance_layout((lispobj*)native_layout) == LAYOUT_OF_LAYOUT);
1701 return native_layout;
1704 static lispobj follow_fp(lispobj ptr)
1706 if (forwarding_pointer_p(native_pointer(ptr)))
1707 return forwarding_pointer_value(native_pointer(ptr));
1708 else
1709 return ptr;
1712 /// It's tricky to try to use the scavtab[] functions for fixing up moved
1713 /// objects, because scavenger functions might invoke transport functions.
1714 /// The best approach is to do an explicit switch over all object types.
1715 #include "genesis/hash-table.h"
1716 static void fixup_space(lispobj* where, size_t n_words)
1718 lispobj* end = where + n_words;
1719 lispobj header_word;
1720 int widetag;
1721 long size;
1722 int static_space_p = ((lispobj)where == STATIC_SPACE_START);
1723 struct code* code;
1725 while (where < end) {
1726 gc_assert(!forwarding_pointer_p(where));
1727 header_word = *where;
1728 if (is_cons_half(header_word)) {
1729 adjust_words(where, 2, 0); // A cons.
1730 where += 2;
1731 continue;
1733 widetag = widetag_of(header_word);
1734 size = sizetab[widetag](where);
1735 switch (widetag) {
1736 default:
1737 if (!unboxed_obj_widetag_p(widetag))
1738 lose("Unhandled widetag in fixup_space: %p\n", (void*)header_word);
1739 break;
1740 #ifdef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1741 case FUNCALLABLE_INSTANCE_WIDETAG:
1742 #endif
1743 case INSTANCE_WIDETAG:
1744 instance_scan(adjust_words, where+1,
1745 instance_length(header_word) | 1,
1746 fix_object_layout(where)->bitmap,
1748 break;
1749 case CODE_HEADER_WIDETAG:
1750 // Fixup the constant pool.
1751 adjust_words(where+1, code_header_words(header_word)-1, 0);
1752 // Fixup all embedded simple-funs
1753 code = (struct code*)where;
1754 for_each_simple_fun(i, f, code, 1, {
1755 f->self = adjust_fun_entrypoint(f->self);
1756 adjust_words(SIMPLE_FUN_SCAV_START(f), SIMPLE_FUN_SCAV_NWORDS(f), 0);
1758 if (code->fixups)
1759 fixup_immobile_refs(follow_fp, code->fixups, code);
1760 break;
1761 case CLOSURE_WIDETAG:
1762 where[1] = adjust_fun_entrypoint(where[1]);
1763 // FALLTHROUGH_INTENDED
1764 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
1765 case FUNCALLABLE_INSTANCE_WIDETAG:
1766 #endif
1767 // skip the trampoline word at where[1]
1768 adjust_words(where+2, size-2, 0);
1769 break;
1770 case FDEFN_WIDETAG:
1771 adjust_words(where+1, 2, 0);
1772 // If fixed-size objects (hence FDEFNs) are movable, then fixing the
1773 // raw address can not be done here, because it is impossible to compute
1774 // the absolute jump target - we don't know what the fdefn's original
1775 // address was to compute a pc-relative address. So we do those while
1776 // permuting the FDEFNs. But because static fdefns do not move,
1777 // we do process their raw address slot here.
1778 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
1779 if (static_space_p)
1780 #endif
1781 adjust_fdefn_entrypoint(where, 0, (struct fdefn*)where);
1782 break;
1784 // Special case because we might need to mark hashtables
1785 // as needing rehash.
1786 case SIMPLE_VECTOR_WIDETAG:
1787 if (is_vector_subtype(header_word, VectorValidHashing)) {
1788 struct vector* v = (struct vector*)where;
1789 lispobj* data = v->data;
1790 gc_assert(v->length > 0 &&
1791 lowtag_of(data[0]) == INSTANCE_POINTER_LOWTAG &&
1792 !(fixnum_value(v->length) & 1)); // length must be even
1793 boolean needs_rehash = 0;
1794 int i;
1795 for (i = fixnum_value(v->length)-1 ; i>=0 ; --i) {
1796 lispobj ptr = data[i];
1797 if (is_lisp_pointer(ptr) && forwarding_pointer_p(native_pointer(ptr))) {
1798 data[i] = forwarding_pointer_value(native_pointer(ptr));
1799 needs_rehash = 1;
1802 if (needs_rehash) {
1803 struct hash_table *ht = (struct hash_table*)native_pointer(v->data[0]);
1804 ht->needs_rehash_p = T;
1806 break;
1807 } else {
1808 // FALLTHROUGH_INTENDED
1810 // All the other array header widetags.
1811 case SIMPLE_ARRAY_WIDETAG:
1812 #ifdef COMPLEX_CHARACTER_STRING_WIDETAG
1813 case COMPLEX_CHARACTER_STRING_WIDETAG:
1814 #endif
1815 case COMPLEX_BASE_STRING_WIDETAG:
1816 case COMPLEX_VECTOR_NIL_WIDETAG:
1817 case COMPLEX_BIT_VECTOR_WIDETAG:
1818 case COMPLEX_VECTOR_WIDETAG:
1819 case COMPLEX_ARRAY_WIDETAG:
1820 // And the other entirely boxed objects.
1821 case SYMBOL_WIDETAG:
1822 case VALUE_CELL_WIDETAG:
1823 case WEAK_POINTER_WIDETAG:
1824 case RATIO_WIDETAG:
1825 case COMPLEX_WIDETAG:
1826 // Use the sizing functions for generality.
1827 // Symbols can contain strange header bytes,
1828 // and vectors might have a padding word, etc.
1829 adjust_words(where+1, size-1, 0);
1830 break;
1832 where += size;
1836 int* immobile_space_reloc_index;
1837 int* immobile_space_relocs;
1839 static int calc_n_pages(int n_objects, int words_per_object)
1841 words_per_object = ALIGN_UP(words_per_object, 2);
1842 int objects_per_page = WORDS_PER_PAGE / words_per_object;
1843 return (n_objects + objects_per_page - 1) / objects_per_page;
1846 // Take and return an untagged pointer, or 0 if the object did not survive GC.
1847 static lispobj* get_load_address(lispobj* old)
1849 if (forwarding_pointer_p(old))
1850 return native_pointer(forwarding_pointer_value(old));
1851 gc_assert(immobile_filler_p(old));
1852 return 0;
1855 // This does not accept (SIMPLE-ARRAY NIL (*))
1856 // (You'd have a pretty bad time trying making a symbol like that)
1857 static int schar(struct vector* string, int index)
1859 #ifdef LISP_FEATURE_SB_UNICODE
1860 if (widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG)
1861 return ((int*)string->data)[index];
1862 #endif
1863 return ((char*)string->data)[index];
1866 #include "genesis/package.h"
1867 #define N_SYMBOL_KINDS 4
1869 // Return an integer 0..3 telling which block of symbols to relocate 'sym' into.
1870 // This is the same as the "symbol kind" in the allocator.
1871 // 0 = uninterned, 1 = keyword, 2 = other interned, 3 = special var
1872 static int classify_symbol(lispobj* obj)
1874 struct symbol* symbol = (struct symbol*)obj;
1875 if (symbol->package == NIL) return 0;
1876 struct vector* package_name = (struct vector*)
1877 native_pointer(((struct package*)native_pointer(symbol->package))->_name);
1878 if (widetag_of(package_name->header) == SIMPLE_BASE_STRING_WIDETAG
1879 && !strcmp((char*)package_name->data, "KEYWORD"))
1880 return 1;
1881 struct vector* symbol_name = VECTOR(symbol->name);
1882 if (symbol_name->length >= make_fixnum(2) &&
1883 schar(symbol_name, 0) == '*' &&
1884 schar(symbol_name, fixnum_value(symbol_name->length)-1) == '*')
1885 return 3;
1886 return 2;
1889 static char* compute_defrag_start_address()
1891 // For technical reasons, objects on the first few pages created by genesis
1892 // must never move at all. So figure out where the end of that subspace is.
1893 lispobj* obj = (lispobj*)IMMOBILE_SPACE_START;
1894 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1895 while (instance_layout(obj) != LAYOUT_OF_PACKAGE) {
1896 obj = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1897 gc_assert(widetag_of(*obj) == INSTANCE_WIDETAG);
1899 // Now find a page that does NOT have a package.
1900 do {
1901 obj = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1902 } while (widetag_of(*obj) == INSTANCE_WIDETAG
1903 && instance_layout(obj) == LAYOUT_OF_PACKAGE);
1904 return (char*)obj;
1907 void defrag_immobile_space(int* components, boolean verbose)
1909 // Find the starting address of fixed-size objects that will undergo defrag.
1910 // Never move the first few pages of LAYOUTs or PACKAGEs created by genesis.
1911 // If codegen becomes smarter, things like layout of FUNCTION and some
1912 // some others can be used as immediate constants in compiled code.
1913 // With initial packages, it's mainly a debugging convenience that they not move.
1914 char* defrag_base = compute_defrag_start_address();
1915 low_page_index_t page_index = find_immobile_page_index(defrag_base);
1916 lispobj* addr;
1917 int i;
1919 // Count the number of symbols, fdefns, and layouts that will be relocated
1920 unsigned int obj_type_histo[64], sym_kind_histo[4];
1921 bzero(obj_type_histo, sizeof obj_type_histo);
1922 bzero(sym_kind_histo, sizeof sym_kind_histo);
1924 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
1925 for ( ; page_index <= max_used_fixedobj_page ; ++page_index) {
1926 int obj_spacing = fixedobj_page_obj_align(page_index);
1927 if (obj_spacing) {
1928 lispobj* obj = low_page_address(page_index);
1929 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
1930 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
1931 lispobj word = *obj;
1932 if (!fixnump(word)) {
1933 if (widetag_of(word) == SYMBOL_WIDETAG)
1934 ++sym_kind_histo[classify_symbol(obj)];
1935 else
1936 ++obj_type_histo[widetag_of(word)/4];
1941 gc_assert(obj_type_histo[INSTANCE_WIDETAG/4]);
1943 // Calculate space needed for fixedobj pages after defrag.
1944 // page order is: layouts, fdefns, GFs, symbols
1945 int n_layout_pages = calc_n_pages(obj_type_histo[INSTANCE_WIDETAG/4],
1946 LAYOUT_ALIGN / N_WORD_BYTES);
1947 int n_fdefn_pages = calc_n_pages(obj_type_histo[FDEFN_WIDETAG/4], FDEFN_SIZE);
1948 int n_fin_pages = calc_n_pages(obj_type_histo[FUNCALLABLE_INSTANCE_WIDETAG/4],
1949 6); // KLUDGE
1950 #if !(defined(LISP_FEATURE_IMMOBILE_CODE) && defined(LISP_FEATURE_COMPACT_INSTANCE_HEADER))
1951 gc_assert(n_fin_pages == 0);
1952 #endif
1953 char* layout_alloc_ptr = defrag_base;
1954 char* fdefn_alloc_ptr = layout_alloc_ptr + n_layout_pages * IMMOBILE_CARD_BYTES;
1955 char* fin_alloc_ptr = fdefn_alloc_ptr + n_fdefn_pages * IMMOBILE_CARD_BYTES;
1956 char* symbol_alloc_ptr[N_SYMBOL_KINDS+1];
1957 symbol_alloc_ptr[0] = fin_alloc_ptr + n_fin_pages * IMMOBILE_CARD_BYTES;
1958 for (i=0; i<N_SYMBOL_KINDS ; ++i)
1959 symbol_alloc_ptr[i+1] = symbol_alloc_ptr[i]
1960 + calc_n_pages(sym_kind_histo[i], SYMBOL_SIZE) * IMMOBILE_CARD_BYTES;
1961 char* ending_alloc_ptr = symbol_alloc_ptr[N_SYMBOL_KINDS];
1963 fixedobj_tempspace.n_bytes = ending_alloc_ptr - (char*)IMMOBILE_SPACE_START;
1964 fixedobj_tempspace.start = calloc(fixedobj_tempspace.n_bytes, 1);
1965 // Copy the first few pages (the permanent pages) from immobile space
1966 // into the temporary copy, so that tempspace_addr()
1967 // does not have to return the unadjusted addr if below defrag_base.
1968 memcpy(fixedobj_tempspace.start, (char*)IMMOBILE_SPACE_START,
1969 (lispobj)defrag_base - IMMOBILE_SPACE_START);
1970 #endif
1972 // Compute where each code component will be moved to.
1973 int n_code_components = 0;
1974 for (i=0 ; components[i*2] ; ++i) {
1975 addr = (lispobj*)(long)components[i*2];
1976 gc_assert(lowtag_of((lispobj)addr) == OTHER_POINTER_LOWTAG);
1977 addr = native_pointer((lispobj)addr);
1978 int widetag = widetag_of(*addr);
1979 lispobj new_vaddr = 0;
1980 // FIXME: generalize
1981 gc_assert(widetag == CODE_HEADER_WIDETAG);
1982 if (!immobile_filler_p(addr)) {
1983 ++n_code_components;
1984 new_vaddr = IMMOBILE_VARYOBJ_SUBSPACE_START + varyobj_tempspace.n_bytes;
1985 varyobj_tempspace.n_bytes += sizetab[widetag](addr) << WORD_SHIFT;
1987 components[i*2+1] = new_vaddr;
1989 varyobj_tempspace.start = calloc(varyobj_tempspace.n_bytes, 1);
1991 if (verbose)
1992 printf("%d+%d+%d+%d objects... ",
1993 obj_type_histo[INSTANCE_WIDETAG/4],
1994 obj_type_histo[FDEFN_WIDETAG/4],
1995 (sym_kind_histo[0]+sym_kind_histo[1]+
1996 sym_kind_histo[2]+sym_kind_histo[3]),
1997 n_code_components);
1999 // Permute varyobj space into tempspace and deposit forwarding pointers.
2000 lispobj new_vaddr;
2001 for (i=0 ; components[i*2] ; ++i) {
2002 if ((new_vaddr = components[i*2+1]) != 0) {
2003 addr = native_pointer(components[i*2]);
2004 memcpy(tempspace_addr((void*)new_vaddr), addr,
2005 sizetab[widetag_of(*addr)](addr) << WORD_SHIFT);
2006 int displacement = new_vaddr - (lispobj)addr;
2007 switch (widetag_of(*addr)) {
2008 case CODE_HEADER_WIDETAG:
2009 for_each_simple_fun(index, fun, (struct code*)addr, 1, {
2010 set_forwarding_pointer((lispobj*)fun,
2011 make_lispobj((char*)fun + displacement,
2012 FUN_POINTER_LOWTAG));
2014 break;
2016 set_forwarding_pointer(addr,
2017 make_lispobj((void*)new_vaddr,
2018 OTHER_POINTER_LOWTAG));
2022 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2023 // Permute fixed-sized object pages and deposit forwarding pointers.
2024 for ( page_index = find_immobile_page_index(defrag_base) ;
2025 page_index <= max_used_fixedobj_page ; ++page_index) {
2026 int obj_spacing = fixedobj_page_obj_align(page_index);
2027 if (!obj_spacing) continue;
2028 lispobj* obj = low_page_address(page_index);
2029 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
2030 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
2031 lispobj word = *obj;
2032 if (fixnump(word) || immobile_filler_p(obj))
2033 continue;
2034 char** alloc_ptr;
2035 int lowtag = OTHER_POINTER_LOWTAG;
2036 int widetag = widetag_of(word);
2037 switch (widetag) {
2038 case INSTANCE_WIDETAG:
2039 alloc_ptr = &layout_alloc_ptr;
2040 lowtag = INSTANCE_POINTER_LOWTAG;
2041 break;
2042 case FUNCALLABLE_INSTANCE_WIDETAG:
2043 alloc_ptr = &fin_alloc_ptr;
2044 lowtag = FUN_POINTER_LOWTAG;
2045 break;
2046 case FDEFN_WIDETAG:
2047 alloc_ptr = &fdefn_alloc_ptr;
2048 break;
2049 case SYMBOL_WIDETAG:
2050 alloc_ptr = &symbol_alloc_ptr[classify_symbol(obj)];
2051 break;
2052 default:
2053 lose("Unexpected widetag");
2055 lispobj* new = (lispobj*)*alloc_ptr;
2056 lispobj end = (lispobj)new + obj_spacing;
2057 #define ALIGN_MASK (IMMOBILE_CARD_BYTES - 1)
2058 if ((end & ALIGN_MASK) < ((lispobj)new & ALIGN_MASK) // wrapped
2059 && (end & ALIGN_MASK) != 0) // ok if exactly on the boundary
2060 new = (lispobj*)(end & ~ALIGN_MASK); // snap to page
2061 #undef ALIGN_MASK
2062 memcpy(tempspace_addr(new), obj, sizetab[widetag](obj) << WORD_SHIFT);
2063 set_forwarding_pointer(obj, make_lispobj(new, lowtag));
2064 *alloc_ptr = (char*)new + obj_spacing;
2067 #ifdef LISP_FEATURE_X86_64
2068 // Fixup JMP offset in fdefns, and self pointers in funcallable instances.
2069 // The former can not be done in the same pass as space permutation,
2070 // because we don't know the order in which a generic function and its
2071 // related fdefn will be reached. Were this attempted in a single pass,
2072 // it could miss a GF that will be moved after the fdefn is moved.
2073 // And it can't be done in fixup_space() because that does not know the
2074 // original address of each fdefn, so can't compute the absolute callee.
2075 for ( page_index = find_immobile_page_index(defrag_base) ;
2076 page_index <= max_used_fixedobj_page ; ++page_index) {
2077 int obj_spacing = fixedobj_page_obj_align(page_index);
2078 if (!obj_spacing) continue;
2079 lispobj* obj = low_page_address(page_index);
2080 lispobj* limit = (lispobj*)((char*)obj + IMMOBILE_CARD_BYTES);
2081 for ( ; obj < limit ; obj = (lispobj*)((char*)obj + obj_spacing) ) {
2082 if (fixnump(*obj) || immobile_filler_p(obj))
2083 continue;
2084 gc_assert(forwarding_pointer_p(obj));
2085 lispobj* new = native_pointer(forwarding_pointer_value(obj));
2086 switch (widetag_of(*tempspace_addr(new))) {
2087 case FDEFN_WIDETAG:
2088 // Fix displacement in JMP or CALL instruction.
2089 adjust_fdefn_entrypoint(tempspace_addr(new),
2090 (char*)new - (char*)obj,
2091 (struct fdefn*)obj);
2092 break;
2093 case FUNCALLABLE_INSTANCE_WIDETAG:
2094 tempspace_addr(new)[1] = (lispobj)(new + 4);
2095 break;
2099 #endif /* LISP_FEATURE_X86_64 */
2100 #endif /* DEFRAGMENT_FIXEDOBJ_SUBSPACE */
2102 #ifdef LISP_FEATURE_X86_64
2103 // Fix displacements in JMP and CALL instructions in code objects.
2104 // There are 2 arrays in use:
2105 // - the relocs[] array contains the address of any machine instruction
2106 // that needs to be altered on account of space relocation.
2107 // - the reloc_index[] array identifes the code component each reloc belongs to.
2108 // It is an array of pairs:
2109 // comp_ptr1, index1, comp_ptr2, index2 ... comp_ptrN, indexN, 0, index_max
2110 // The index following a component specifies the starting index within the
2111 // relocs[] array of the first reloc belonging to the respective component.
2112 // The ending reloc can be deduced from the next component's first reloc.
2113 for (i = 0 ; immobile_space_reloc_index[i*2] ; ++i) {
2114 lispobj code = immobile_space_reloc_index[i*2] - OTHER_POINTER_LOWTAG;
2115 lispobj load_addr;
2116 if (code >= READ_ONLY_SPACE_START && code < READ_ONLY_SPACE_END)
2117 load_addr = code; // This code can not be moved or GCed.
2118 else
2119 load_addr = (lispobj)get_load_address((lispobj*)code);
2120 if (!load_addr) continue; // Skip code that was dropped by GC
2121 int reloc_index = immobile_space_reloc_index[i*2+1];
2122 int end_reloc_index = immobile_space_reloc_index[i*2+3];
2123 for ( ; reloc_index < end_reloc_index ; ++reloc_index ) {
2124 unsigned char* inst_addr = (unsigned char*)(long)immobile_space_relocs[reloc_index];
2125 gc_assert(*inst_addr == 0xE8 || *inst_addr == 0xE9);
2126 unsigned int target_addr = (int)(long)inst_addr + 5 + *(int*)(inst_addr+1);
2127 int target_adjust = 0;
2128 // Both this code and the jumped-to code can move.
2129 // For this component, adjust by the displacement by (old - new).
2130 // If the jump target moved, also adjust by its (new - old).
2131 // The target address can point to one of:
2132 // - an FDEFN raw addr slot (fixedobj subspace)
2133 // - funcallable-instance with self-contained trampoline (ditto)
2134 // - a simple-fun that was statically linked (varyobj subspace)
2135 if (immobile_space_p(target_addr)) {
2136 lispobj *obj = target_addr < IMMOBILE_VARYOBJ_SUBSPACE_START
2137 ? search_immobile_space((void*)(uword_t)target_addr)
2138 : defrag_search_varyobj_subspace(target_addr);
2139 if (forwarding_pointer_p(obj))
2140 target_adjust = (int)((char*)native_pointer(forwarding_pointer_value(obj))
2141 - (char*)obj);
2143 // If the instruction to fix has moved, then adjust for
2144 // its new address, and perform the fixup in tempspace.
2145 // Otherwise perform the fixup where the instruction is now.
2146 char* fixup_loc = (immobile_space_p((lispobj)inst_addr) ?
2147 (char*)tempspace_addr(inst_addr - code + load_addr) :
2148 (char*)inst_addr) + 1;
2149 *(int*)fixup_loc += target_adjust + (code - load_addr);
2152 #endif
2153 free(immobile_space_relocs);
2154 free(immobile_space_reloc_index);
2156 // Fix Lisp pointers in static, immobile, and dynamic spaces
2157 fixup_space((lispobj*)STATIC_SPACE_START,
2158 static_space_free_pointer - (lispobj*)STATIC_SPACE_START);
2160 // Objects in immobile space are physically at 'tempspace',
2161 // but logically at their natural address. Perform fixups
2162 // at their current physical address.
2163 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2164 fixup_space((lispobj*)fixedobj_tempspace.start,
2165 fixedobj_tempspace.n_bytes >> WORD_SHIFT);
2166 #else
2167 fixup_space((lispobj*)IMMOBILE_SPACE_START,
2168 IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE >> WORD_SHIFT);
2169 #endif
2170 fixup_space((lispobj*)varyobj_tempspace.start,
2171 varyobj_tempspace.n_bytes >> WORD_SHIFT);
2173 // Dynamic space
2174 // We can safely ignore allocation region boundaries.
2175 fixup_space(current_dynamic_space,
2176 (lispobj*)get_alloc_pointer() - current_dynamic_space);
2178 // Copy the spaces back where they belong.
2180 // Fixed-size objects: don't copy below the defrag_base - the first few
2181 // pages are totally static in regard to both lifetime and placement.
2182 // (It would "work" to copy them back - since they were copied into
2183 // the temp space, but it's just wasting time to do so)
2184 lispobj old_free_ptr;
2185 lispobj free_ptr;
2186 #if DEFRAGMENT_FIXEDOBJ_SUBSPACE
2187 int n_static_bytes = ((lispobj)defrag_base - IMMOBILE_SPACE_START);
2188 memcpy((char*)defrag_base,
2189 fixedobj_tempspace.start + n_static_bytes,
2190 fixedobj_tempspace.n_bytes - n_static_bytes);
2191 // Zero-fill the unused remainder
2192 old_free_ptr = (lispobj)immobile_fixedobj_free_pointer;
2193 free_ptr = IMMOBILE_SPACE_START + fixedobj_tempspace.n_bytes;
2194 bzero((char*)free_ptr, old_free_ptr - free_ptr);
2195 immobile_fixedobj_free_pointer = (lispobj*)free_ptr;
2196 #endif
2198 // Variable-size object pages.
2199 memcpy((char*)IMMOBILE_VARYOBJ_SUBSPACE_START,
2200 varyobj_tempspace.start, varyobj_tempspace.n_bytes);
2201 // Zero-fill the unused remainder
2202 old_free_ptr = (lispobj)immobile_space_free_pointer;
2203 free_ptr = IMMOBILE_VARYOBJ_SUBSPACE_START + varyobj_tempspace.n_bytes;
2204 bzero((char*)free_ptr, old_free_ptr - free_ptr);
2205 immobile_space_free_pointer = (lispobj*)free_ptr;
2206 free(components);
2207 page_attributes_valid = 0;
2208 #if 0
2209 // It's easy to mess things up, so assert correctness before saving a core.
2210 printf("verifying defrag\n");
2211 verify_gc(0);
2212 printf("verify passed\n");
2213 #endif
2214 free(fixedobj_tempspace.start);
2215 free(varyobj_tempspace.start);
2217 #endif
2219 void verify_immobile_page_protection(int keep_gen, int new_gen)
2221 low_page_index_t page;
2222 lispobj* end = immobile_space_free_pointer;
2223 low_page_index_t end_page = find_immobile_page_index((char*)end-1);
2224 lispobj* obj;
2226 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2227 if (!varyobj_page_touched(page)) {
2228 lispobj* page_begin = low_page_address(page);
2229 lispobj* page_end = page_begin + WORDS_PER_PAGE;
2230 // Assert that there are no old->young pointers.
2231 obj = varyobj_scan_start(page);
2232 // Never scan past the free pointer.
2233 // FIXME: It is is supposed to work to scan past the free pointer
2234 // on the last page, but the allocator needs to plop an array header there,
2235 // and sometimes it doesn't.
2236 lispobj* varyobj_free_ptr = immobile_space_free_pointer;
2237 if (page_end > varyobj_free_ptr) page_end = varyobj_free_ptr;
2238 for ( ; obj < page_end ; obj += sizetab[widetag_of(*obj)](obj) ) {
2239 if (!immobile_filler_p(obj)
2240 && varyobj_points_to_younger_p(obj, __immobile_obj_gen_bits(obj),
2241 keep_gen, new_gen,
2242 (char*)page_begin, (char*)page_end))
2243 lose("page WP bit on page %d is wrong\n", page);
2249 // Fixup immediate values that encode Lisp object addresses
2250 // in immobile space.
2251 // TODO: remove the fixup_lispobj function; this doesn't generalize
2252 // as originally thought. coreparse has its own way of doing things.
2253 #include "forwarding-ptr.h"
2254 #ifdef LISP_FEATURE_X86_64
2255 void fixup_immobile_refs(lispobj (*fixup_lispobj)(lispobj),
2256 lispobj fixups, struct code* code)
2258 struct varint_unpacker unpacker;
2259 varint_unpacker_init(&unpacker, fixups);
2260 char* instructions = (char*)((lispobj*)code + code_header_words(code->header));
2261 int prev_loc = 0, loc;
2262 while (varint_unpack(&unpacker, &loc) && loc != 0) {
2263 // For extra compactness, each loc is relative to the prior,
2264 // so that the magnitudes are smaller.
2265 loc += prev_loc;
2266 prev_loc = loc;
2267 int* fixup_where = (int*)(instructions + loc);
2268 lispobj ptr = (lispobj)(*fixup_where);
2269 if (is_lisp_pointer(ptr)) {
2270 lispobj fixed = fixup_lispobj(ptr);
2271 if (fixed != ptr)
2272 *fixup_where = fixed;
2273 } else {
2274 lispobj* header_addr;
2275 if (ptr < IMMOBILE_VARYOBJ_SUBSPACE_START) {
2276 // It's an absolute interior pointer to a symbol value slot
2277 // or an fdefn raw address slot.
2278 header_addr = search_immobile_space((void*)ptr);
2279 gc_assert(header_addr);
2280 if (forwarding_pointer_p(header_addr)) {
2281 lispobj fpval = forwarding_pointer_value(header_addr);
2282 *fixup_where = (int)(long)native_pointer(fpval)
2283 + (ptr - (lispobj)header_addr);
2285 } else if (ptr > asm_routines_end) {
2286 /* Carefully avoid looking at assembler routines, which precede
2287 * all other code in immobile code space. As currently implemented,
2288 * defragmentation deposits a FP into the code header for those
2289 * routines, each "forwarding" to itself, since it won't move.
2290 * A dynamic space call is emitted as "MOV Rnn, {addr} ; CALL Rnn"
2291 * where #x{addr} is exactly 6 words beyond the header word
2292 * for the first routine, which happens to be ALLOC-TO-R11.
2293 * Dereferencing (ptr-offsetof(struct simple_fun, code)) for that
2294 * would see a forwarding pointer and try to assert that the called
2295 * object is a simple-fun. Don't do it!
2296 * If calling a second or later routine within an assembler component,
2297 * it doesn't even make sense to read the word at ptr-N because
2298 * the bits are random-ish. So even more emphatically don't do that. */
2299 header_addr = (lispobj*)(ptr - offsetof(struct simple_fun, code));
2300 if (forwarding_pointer_p(header_addr)) {
2301 lispobj fpval = forwarding_pointer_value(header_addr);
2302 // It must be the entrypoint to a static [sic] function.
2303 gc_assert(widetag_of(*tempspace_addr(native_pointer(fpval)))
2304 == SIMPLE_FUN_WIDETAG);
2305 *fixup_where = fpval + FUN_RAW_ADDR_OFFSET;
2311 #endif
2313 #ifdef VERIFY_PAGE_GENS
2314 void check_fixedobj_page(int page)
2316 // Every page should have a 'gens' mask which exactly reflects
2317 // the aggregate over all objects on that page. Verify that invariant,
2318 // checking all pages, not just the ones below the free pointer.
2319 int genmask, obj_size, obj_spacing, i, all_ok = 1;
2320 lispobj *obj, *limit, header;
2321 int sees_younger = 0;
2323 obj_size = fixedobj_page_obj_size(page);
2324 obj_spacing = fixedobj_page_obj_align(page);
2325 obj = low_page_address(page);
2326 limit = (lispobj*)((char*)(obj + WORDS_PER_PAGE) - obj_spacing);
2327 genmask = 0;
2328 if (obj_size == 0) {
2329 for (i=0; i<WORDS_PER_PAGE; ++i)
2330 gc_assert(obj[i]==0);
2331 gc_assert(fixedobj_pages[page].gens ==0);
2332 return;
2334 for ( ; obj <= limit ; obj += obj_spacing ) {
2335 header = *obj;
2336 if (!fixnump(header)) {
2337 int gen = __immobile_obj_gen_bits(obj);
2338 gc_assert(0 <= gen && gen <= PSEUDO_STATIC_GENERATION);
2339 genmask |= 1<<gen;
2340 if (fixedobj_points_to_younger_p(obj, obj_size, gen, 0xff, 0xff))
2341 sees_younger = 1;
2344 // It's not wrong if the gen0 bit is set spuriously, but it should only
2345 // happen at most once, on the first GC after image startup.
2346 // At all other times, the invariant should hold that if the freelist
2347 // indicated that space was available, and the new pointer differs,
2348 // then some gen0 object exists on the page.
2349 // The converse is true because of pseudo-atomicity of the allocator:
2350 // if some thread claimed a hole, then it also updated the freelist.
2351 // If it died before doing the latter, then the object allegedly created
2352 // was never really live, so won't contain any pointers.
2353 if (fixedobj_pages[page].gens != genmask
2354 && fixedobj_pages[page].gens != (genmask|1)) {
2355 fprintf(stderr, "Page #x%x @ %p: stored mask=%x actual=%x\n",
2356 page, low_page_address(page),
2357 fixedobj_pages[page].gens, genmask);
2358 all_ok = 0;
2360 if (fixedobj_page_wp(page) && sees_younger) {
2361 fprintf(stderr, "Page #x%x @ %p: WP is wrong\n",
2362 page, low_page_address(page));
2363 all_ok = 0;
2365 gc_assert(all_ok);
2368 int n_immobile_objects;
2369 int *immobile_objects, *immobile_objects_limit;
2371 int comparator_eq(const void* a, const void* b) {
2372 return *(int*)a - *(int*)b;
2375 // Find the largest item less than or equal.
2376 // (useful for finding the object that contains a given pointer)
2377 int comparator_le(const void* a, const void* b) {
2378 int diff = *(int*)a - *(int*)b;
2379 if (diff <= 0) return diff;
2380 // If looking to the right would see an item strictly greater
2381 // than the sought key, or there is nothing to the right,
2382 // then deem this an exact match.
2383 if (b == (void*)immobile_objects_limit || ((int*)b)[1] > *(int*)a) return 0;
2384 return 1;
2387 // Find the smallest item greater than or equal.
2388 // useful for finding the lowest item at or after a page base address.
2389 int comparator_ge(const void* a, const void* b) {
2390 int diff = *(int*)a - *(int*)b;
2391 if (diff >= 0) return diff;
2392 // If looking to the left would see an item strictly less
2393 // than the sought key, or there is nothing to the left
2394 // then deem this an exact match.
2395 if (b == (void*)immobile_objects || ((int*)b)[-1] < *(int*)a) return 0;
2396 return -1;
2399 void check_varyobj_pages()
2401 // 1. Check that a linear scan sees only valid object headers,
2402 // and that it terminates exactly at IMMOBILE_CODE_FREE_POINTER.
2403 lispobj* obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
2404 lispobj* end = immobile_space_free_pointer;
2405 low_page_index_t end_page = find_immobile_page_index((char*)end-1);
2407 n_immobile_objects = 0;
2408 while (obj < end) {
2409 lispobj word = *obj;
2410 gc_assert(other_immediate_lowtag_p(word));
2411 int n_words = sizetab[widetag_of(word)](obj);
2412 obj += n_words;
2413 ++n_immobile_objects;
2415 gc_assert(obj == end);
2417 // 2. Check that all scan_start_offsets are plausible.
2418 // Begin by collecting all object header locations into an array;
2419 immobile_objects = calloc(n_immobile_objects, sizeof (lispobj));
2420 immobile_objects_limit = immobile_objects + n_immobile_objects - 1;
2421 obj = (lispobj*)IMMOBILE_VARYOBJ_SUBSPACE_START;
2422 int i = 0;
2423 while (obj < end) {
2424 immobile_objects[i++] = (lispobj)obj;
2425 lispobj word = *obj;
2426 int n_words = sizetab[widetag_of(word)](obj);
2427 obj += n_words;
2429 // Check that each page's scan start is a known immobile object
2430 // and that it is the right object.
2431 low_page_index_t page;
2432 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2433 lispobj page_addr = (lispobj)low_page_address(page);
2434 int* found_below = bsearch(&page_addr, immobile_objects, n_immobile_objects,
2435 sizeof (int), comparator_le);
2436 int* found_above = bsearch(&page_addr, immobile_objects, n_immobile_objects,
2437 sizeof (int), comparator_ge);
2438 int stored_scan_start = (int)(long)varyobj_scan_start(page);
2439 lispobj* scan_start_obj = (lispobj*)(long)*found_below;
2440 if (scan_start_obj != (lispobj*)(long)stored_scan_start) {
2441 //printf("page %d: found-below=%p stored=%p\n", page, scan_start_obj, stored_scan_start);
2442 while (immobile_filler_p(scan_start_obj)) {
2443 int nwords = sizetab[widetag_of(*scan_start_obj)](scan_start_obj);
2444 // printf("skipping %d words to %p\n", nwords, scan_start_obj + nwords);
2445 scan_start_obj += nwords;
2446 // the stored scan start does not guarantee that it points
2447 // to a non-hole; we only assert that it *probably* does not.
2448 // As such, when computing the "correct" value, we allow
2449 // any value in between the legal bounding values for it.
2450 if ((int)(long)scan_start_obj == stored_scan_start)
2451 break;
2452 // If you hit the free pointer, or run off the page,
2453 // then the page is completely empty.
2454 if (scan_start_obj == immobile_space_free_pointer
2455 || scan_start_obj >= (lispobj*)low_page_address(page+1)) {
2456 scan_start_obj = low_page_address(page+1);
2457 break;
2461 if (scan_start_obj != (lispobj*)(long)stored_scan_start)
2462 lose("page %d: stored_scan_start=%p does not match found %p\n",
2463 page, stored_scan_start, *found_below);
2464 if (found_below != found_above) {
2465 // the object below must touch this page.
2466 // if it didn't, there should be a higher object below.
2467 lispobj* below = (lispobj*)(long)*found_below;
2468 int n_words = sizetab[widetag_of(*below)](below);
2469 lispobj* end = below + n_words;
2470 gc_assert(end > (lispobj*)page_addr);
2473 free(immobile_objects);
2475 // 3. The generation mask for each page is exactly the union
2476 // of generation numbers of object headers on the page.
2477 for (page = FIRST_VARYOBJ_PAGE; page <= end_page; ++page) {
2478 if (!varyobj_page_scan_start_offset[page - FIRST_VARYOBJ_PAGE])
2479 continue; // page is all holes or never used
2480 obj = varyobj_scan_start(page);
2481 lispobj word = *obj;
2482 int n_words = sizetab[widetag_of(word)](obj);
2483 // Skip the first object if it doesn't start on this page.
2484 if (obj < (lispobj*)low_page_address(page)) obj += n_words;
2485 lispobj* limit = (lispobj*)low_page_address(page) + WORDS_PER_PAGE;
2486 lispobj* freeptr = immobile_space_free_pointer;
2487 if (limit > freeptr) limit = freeptr;
2488 int mask = 0;
2489 for ( ; obj < limit ; obj += sizetab[widetag_of(*obj)](obj) ) {
2490 int gen = __immobile_obj_gen_bits(obj);
2491 if (immobile_filler_p(obj)) {
2492 gc_assert(gen == 0);
2493 } else {
2494 gc_assert(0 <= gen && gen <= PSEUDO_STATIC_GENERATION);
2495 mask |= 1 << gen;
2498 gc_assert(mask == VARYOBJ_PAGE_GENS(page));
2501 #endif