Remove need_zerofill bit from page table

It suffices to indicate in the first word of each free page whether
it ever held data before. After zeroing the page there is no other bit
to affect, since zeroing clears the logical "need_zerofill" flag.
This change was made possible by git rev 20b48b83ae.
This commit is contained in:
Douglas Katzman 2022-06-07 16:23:47 -04:00
parent 542e03d705
commit 938320b209
11 changed files with 31 additions and 56 deletions

View file

@ -829,9 +829,7 @@ Experimental: interface subject to change."
(let* ((wp (page-protected-p object))
(index (sb-vm:find-page-index
(get-lisp-obj-address object)))
(flags (sb-alien:slot page 'sb-vm::flags))
(type #+little-endian (ldb (byte 6 0) flags)
#+big-endian (ldb (byte 6 2) flags)))
(type (sb-alien:slot page 'sb-vm::flags)))
(list :space space
:generation (sb-alien:slot page 'sb-vm::gen)
:write-protected wp

View file

@ -405,10 +405,7 @@ We could try a few things to mitigate this:
end-page-bytes-used)
most-positive-word)))))
(when (sap> end start)
;; The bits in the 6-bit 'type' field have fixed positions,
;; but the position of the field itself depends on endianness.
(let ((flags (ldb (byte 6 (+ #+big-endian 2))
(slot (deref page-table start-page) 'flags))))
(let ((flags (slot (deref page-table start-page) 'flags)))
;; The GEN slot is declared as (SIGNED 8) which does not satisfy the
;; type restriction on the first argument to LOGBITP.
;; Masking it to 3 bits fixes that, and allows using the other 5 bits
@ -1157,8 +1154,8 @@ We could try a few things to mitigate this:
(setq page-num next-page seen-filler nil))))))))
(let ((i 0))
(loop while (< i total-pages)
do (let ((type (ldb (byte 2 0) (slot (deref page-table i) 'flags))))
(if (= type 3)
do (let ((type (slot (deref page-table i) 'flags)))
(if (= (logand type 7) 7)
(setq i (dump-page i))
(incf i)))))
(let* ((n-pages (count 1 pages))
@ -1227,8 +1224,7 @@ We could try a few things to mitigate this:
;; gen0 conses on MIXED pages, but even that is not enough- pinned conses
;; will promote but keep their MIXED page type. So don't bother with this.
#+use-cons-region
(let* ((flags (slot (deref page-table (find-page-index obj-addr)) 'flags))
(type (ldb (byte 6 (+ #+big-endian 2)) flags))
(let* ((type (slot (deref page-table (find-page-index obj-addr)) 'flags))
(ok (if (consp obj)
(or (= type #b101) ; PAGE_TYPE_CONS
(and (eq (car obj) 0) (eq (cdr obj) 0)))

View file

@ -711,7 +711,7 @@ void execute_full_sweep_phase()
for (page = free_page; page < page_table_pages; ++page) {
gc_assert((page_table[page].type & PAGE_TYPE_MASK) == PAGE_TYPE_UNBOXED);
gc_assert(!page_bytes_used(page));
set_page_need_to_zero(page, 1);
set_page_needs_zerofill(page);
page_table[page].type = FREE_PAGE_FLAG;
}
}

View file

@ -30,7 +30,12 @@
#endif
#define GENCGC_PAGE_WORDS (GENCGC_PAGE_BYTES/N_WORD_BYTES)
extern char *page_address(page_index_t);
/* Calculate the start address for the given page number. */
static inline char *page_address(page_index_t page_num) {
return (void*)(DYNAMIC_SPACE_START + (page_num * GENCGC_PAGE_BYTES));
}
int gencgc_handle_wp_violation(void *);
@ -121,7 +126,6 @@ struct page {
// !!! If bit positions are changed, be sure to reflect the changes into
// page_extensible_p() as well as ALLOCATION-INFORMATION in sb-introspect
// and WALK-DYNAMIC-SPACE.
unsigned char
/*
* The 4 low bits of 'type' are defined by PAGE_TYPE_x constants.
* 0000 free
@ -130,11 +134,7 @@ struct page {
* ?011 mixed boxed/unboxed non-code objects
* ?111 code
* The next two bits are SINGLE_OBJECT and OPEN_REGION */
type :6,
/* Whether the page was used at all. This is the only bit that can
* be 1 on a free page */
need_zerofill :1,
dontuse :1;
unsigned char type;
/* the generation that this page belongs to. This should be valid
* for all pages that may have objects allocated, even current

View file

@ -18,12 +18,12 @@ typedef unsigned int page_bytes_t;
#define page_words_used(index) page_table[index].words_used_
#define page_bytes_used(index) ((page_bytes_t)page_table[index].words_used_<<WORD_SHIFT)
#if defined LISP_FEATURE_RISCV && defined LISP_FEATURE_LINUX // KLUDGE
#define page_need_to_zero(index) (mmap_does_not_zero || page_table[index].need_zerofill)
#define page_need_to_zero(index) (mmap_does_not_zero || (*(uword_t*)page_address(index) != 0))
#else
#define page_need_to_zero(index) page_table[index].need_zerofill
#define page_need_to_zero(index) (*(uword_t*)page_address(index) != 0)
#endif
#define set_page_bytes_used(index,val) page_table[index].words_used_ = ((val)>>WORD_SHIFT)
#define set_page_need_to_zero(index,val) page_table[index].need_zerofill = val
#define set_page_needs_zerofill(index) *(uword_t*)page_address(index) = 0xBADBAD
#if !CONDENSED_PAGE_TABLE

View file

@ -193,12 +193,6 @@ static inline boolean protect_page_p(page_index_t page, generation_index_t gener
}
#endif
/* Calculate the start address for the given page number. */
inline char *page_address(page_index_t page_num)
{
return (void*)(DYNAMIC_SPACE_START + (page_num * GENCGC_PAGE_BYTES));
}
/* Calculate the address where the allocation region associated with
* the page starts. */
static inline void *
@ -262,12 +256,10 @@ page_index_t contiguous_block_final_page(page_index_t first) {
/* We maintain the invariant that pages with FREE_PAGE_FLAG have
* scan_start of zero, to optimize page_ends_contiguous_block_p().
* Clear all the flags that don't pertain to a free page.
* Particularly the 'need_zerofill' bit MUST remain as-is */
* Clear all the flags that don't pertain to a free page. */
static inline void reset_page_flags(page_index_t page) {
page_table[page].scan_start_offset_ = 0;
page_table[page].type = 0;
page_table[page].dontuse = 0;
gc_page_pins[page] = 0;
// Why can't the 'gen' get cleared? It caused failures. THIS MAKES NO SENSE!!!
// page_table[page].gen = 0;
@ -778,7 +770,7 @@ void zeroize_pages_if_needed(page_index_t start, page_index_t end, int page_type
for (i = start; i <= end; i++) any_need_to_zero |= page_need_to_zero(i);
if (any_need_to_zero) {
zero_pages(start, end);
for (i = start; i <= end; i++) set_page_need_to_zero(i, 0);
// Zeroing the page clears the need-to-zerofill status implicitly
}
#else
boolean usable_by_lisp =
@ -788,7 +780,7 @@ void zeroize_pages_if_needed(page_index_t start, page_index_t end, int page_type
for (i = start; i <= end; i++)
if (page_need_to_zero(i)) {
zero_pages(i, i);
set_page_need_to_zero(i, 0);
// Zeroing the page clears the need-to-zerofill status implicitly
}
}
#endif
@ -939,18 +931,11 @@ page_extensible_p(page_index_t index, generation_index_t gen, int type) {
&& page_table[index].gen == gen
&& !gc_page_pins[index];
#else
/* Test the three conditions above as a single comparison.
*
* pin -\
* v vvvvvv -- type
* #b11111111_10111111
* ^
* need_zerofill (ignored)
*
* The flags reside at 1 byte prior to 'gen' in the page structure.
/* Test 'gen' and 'type' as one comparison.
* The type is at 1 byte prior to 'gen' in the page structure.
*/
int attributes_match =
(*(int16_t*)(&page_table[index].gen-1) & 0xFFBF) == ((gen<<8)|type);
*(int16_t*)(&page_table[index].gen-1) == ((gen<<8)|type);
#endif
#ifdef LISP_FEATURE_SOFT_CARD_MARKS
return attributes_match && page_cards_all_marked_nonsticky(index);
@ -1753,7 +1738,7 @@ static uword_t adjust_obj_ptes(page_index_t first_page,
#endif
/* It checks out OK, free the page. */
prev_bytes_used = page_bytes_used(page);
set_page_need_to_zero(page, 1);
set_page_needs_zerofill(page);
set_page_bytes_used(page, 0);
reset_page_flags(page);
bytes_freed += prev_bytes_used;
@ -3403,7 +3388,7 @@ static void free_oldspace(void)
gc_dcheck(page_cards_all_marked_nonsticky(last_page));
/* Free the page. */
int used = page_words_used(page);
if (used) set_page_need_to_zero(page, 1);
if (used) set_page_needs_zerofill(page);
set_page_bytes_used(page, 0);
reset_page_flags(page);
bytes_freed += used << WORD_SHIFT;
@ -4401,8 +4386,7 @@ remap_page_range (page_index_t from, page_index_t to)
zero_pages(from, to);
}
#endif
page_index_t i;
for (i = from; i <= to; i++) set_page_need_to_zero(i, 0);
// Zeroing the range clears the need-to-zerofill status implicitly
}
static void

View file

@ -114,7 +114,7 @@ static void release_pages_impl()
if (PRIVATE_CONS_DEBUG)
fprintf(stderr, "Freeing GC-private page @ %p (index %ld)\n",
list, (long)index);
set_page_need_to_zero(index, 1);
set_page_needs_zerofill(index);
set_page_bytes_used(index, 0);
reset_page_flags(index);
}

View file

@ -8,8 +8,7 @@
(sb-vm:find-page-index
(sb-kernel:get-lisp-obj-address x)))
'sb-vm::flags))))
(logbitp 4 ; SINGLE_OBJECT_FLAG
(ldb (byte 6 (+ #+big-endian 2)) flags)))))
(logbitp 4 flags)))) ; SINGLE_OBJECT_FLAG
(compile 'on-large-page-p)
;;; Pseudo-static large objects should retain the single-object flag

View file

@ -41,9 +41,8 @@
(declare (ignore widetag))
(let* ((index
(sb-vm::find-page-index (sb-kernel:get-lisp-obj-address obj)))
(type (ldb (byte 6 (+ #+big-endian 2))
(sb-alien:slot (sb-alien:deref sb-vm::page-table index)
'sb-vm::flags))))
(type (sb-alien:slot (sb-alien:deref sb-vm::page-table index)
'sb-vm::flags)))
;; mask off the SINGLE_OBJECT and OPEN_REGION bits
(when (and (eq (logand type 7) 2) ; PAGE_TYPE_BOXED
;; Cons cells on boxed pags are page filler

View file

@ -24,7 +24,6 @@ static void make_instances(int page_type, generation_index_t gen, lispobj result
page_table[page].gen = 1;
gc_assert(page_table[page].scan_start_offset_ == 0);
page_table[page].words_used_ = (2 * GENCGC_CARD_BYTES) >> WORD_SHIFT;
page_table[page].need_zerofill = 1;
bytes_allocated += 2 * GENCGC_CARD_BYTES;
generations[gen].bytes_allocated += 2 * GENCGC_CARD_BYTES;

View file

@ -34,8 +34,8 @@
#+gencgc
(progn
(defun page-need-to-zero (index)
(logbitp #+little-endian 6 #+big-endian 1
(slot (deref sb-vm::page-table index) 'sb-vm::flags)))
(let ((addr (+ sb-vm:dynamic-space-start (* index sb-vm:gencgc-page-bytes))))
(/= 0 (sb-sys:sap-ref-word (sb-sys:int-sap addr) 0))))
(defun test-private-consing ()
(let ((conses-per-page ; subtract one for the page header cons
(1- (/ sb-vm:gencgc-page-bytes (* 2 sb-vm:n-word-bytes))))