mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
Always define page_words_t as 'unsigned short'
And rob 1 bit of that, so it's effectively 15 bits, not 16.
Then free up 2 more bits of 'type' for other use as I tried to do
in rev 938320b209 which was reverted. Taking a different bit in the
PTE should be fine, and the resulting code looks better for it.
This commit is contained in:
parent
1a0a291c06
commit
3bfea7ffd3
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -483,14 +483,9 @@ statistics are appended to it."
|
|||
;; but if 64-bit then we have to scale the value. Additionally
|
||||
;; there is a fallback for when even the scaled value is too big.
|
||||
(sb-vm::start #+64-bit (unsigned 32) #-64-bit signed)
|
||||
;; On platforms with small enough GC pages, this field
|
||||
;; will be a short. On platforms with larger ones, it'll
|
||||
;; be an int. It should probably never be an int.
|
||||
(sb-vm::words-used (unsigned
|
||||
#.(if (typep sb-vm::gencgc-page-words '(unsigned-byte 16))
|
||||
16
|
||||
32)))
|
||||
(sb-vm::flags (unsigned 8)) ; in C this is {type, need_zerofill, pinned}
|
||||
;; Caution: The low bit of WORDS-USED* is a flag bit
|
||||
(sb-vm::words-used* (unsigned 16)) ; (* in the name is a memory aid)
|
||||
(sb-vm::flags (unsigned 8)) ; this named 'type' in C
|
||||
(sb-vm::gen (signed 8))))
|
||||
(define-alien-variable ("page_table" sb-vm:page-table) (* (struct sb-vm::page)))
|
||||
(declaim (inline sb-vm:find-page-index))
|
||||
|
|
|
|||
|
|
@ -386,7 +386,8 @@ We could try a few things to mitigate this:
|
|||
start-page end-page))
|
||||
(setq end-page start-page)
|
||||
(loop (setq end-page-bytes-used
|
||||
(ash (slot (deref page-table end-page) 'words-used) word-shift))
|
||||
(ash (ash (slot (deref page-table end-page) 'words-used*) -1)
|
||||
word-shift))
|
||||
;; See 'page_ends_contiguous_block_p' in gencgc.c
|
||||
(when (or (< end-page-bytes-used gencgc-page-bytes)
|
||||
(= (slot (deref page-table (1+ end-page)) 'start) 0))
|
||||
|
|
@ -400,10 +401,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 +1155,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 +1225,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)))
|
||||
|
|
|
|||
|
|
@ -48,15 +48,16 @@ int gencgc_handle_wp_violation(void*, void*);
|
|||
# define CONDENSED_PAGE_TABLE 0
|
||||
#endif
|
||||
|
||||
#if GENCGC_PAGE_WORDS > USHRT_MAX
|
||||
# if GENCGC_PAGE_WORDS > UINT_MAX
|
||||
/* One bit of page_words_t is the need_zerofill flag.
|
||||
* That leaves 15 bits to store page_words_used. This can represent
|
||||
* a page size of up to 64KiB on 32-bit and 128KiB on 64-bit.
|
||||
* Note that since the allocation quantum is actually 2 words
|
||||
* the words_used is always an even number, and so technically
|
||||
* we could store as "dualwords used" to achieve double the range */
|
||||
#if GENCGC_PAGE_WORDS > 32767
|
||||
# error "GENCGC_PAGE_WORDS unexpectedly large."
|
||||
# else
|
||||
typedef unsigned int page_words_t;
|
||||
# endif
|
||||
#else
|
||||
typedef unsigned short page_words_t;
|
||||
#endif
|
||||
typedef unsigned short page_words_t;
|
||||
|
||||
/* New objects are allocated to PAGE_TYPE_MIXED or PAGE_TYPE_CONS */
|
||||
/* If you change these constants, then possibly also change the following
|
||||
|
|
@ -114,14 +115,22 @@ struct page {
|
|||
|
||||
/* the number of lispwords of this page that are used. This may be less
|
||||
* than the usage at an instant in time for pages within the current
|
||||
* allocation regions. MUST be 0 for unallocated pages.
|
||||
*/
|
||||
page_words_t words_used_;
|
||||
* allocation regions. The 0th bit of the physical uint16 indicates
|
||||
* that the page needs to be zero-filled for the next use.
|
||||
* Let the C compiler figure it out, so we can't get it wrong in C.
|
||||
* But we need to reverse the order of the packed fields depending on
|
||||
* endianness so that the Lisp side is easier to understand */
|
||||
#ifdef LISP_FEATURE_BIG_ENDIAN
|
||||
page_words_t words_used_ : 15;
|
||||
page_words_t need_zerofill : 1;
|
||||
#else
|
||||
page_words_t need_zerofill : 1;
|
||||
page_words_t words_used_ : 15;
|
||||
#endif
|
||||
|
||||
// !!! 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
|
||||
|
|
@ -129,12 +138,12 @@ struct page {
|
|||
* ?010 strictly unboxed data
|
||||
* ?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;
|
||||
* The next two bits are SINGLE_OBJECT and OPEN_REGION.
|
||||
* The top two can be used for segregating objects by widetag
|
||||
* which will important once we have "destructors" to run for a
|
||||
* for a category of object, such as SYMBOL, hypothetically for
|
||||
* recycling TLS indices or something like that. */
|
||||
unsigned char type;
|
||||
|
||||
/* the generation that this page belongs to. This should be valid
|
||||
* for all pages that may have objects allocated, even current
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@ static inline void reset_page_flags(page_index_t page) {
|
|||
if (page_table[page].type == PAGE_TYPE_CODE) set_page_need_to_zero(page, 1);
|
||||
#endif
|
||||
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;
|
||||
|
|
@ -955,18 +954,8 @@ 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.
|
||||
*/
|
||||
int attributes_match =
|
||||
(*(int16_t*)(&page_table[index].gen-1) & 0xFFBF) == ((gen<<8)|type);
|
||||
*(int16_t*)&page_table[index].type == ((gen<<8)|type);
|
||||
#endif
|
||||
#ifdef LISP_FEATURE_SOFT_CARD_MARKS
|
||||
return attributes_match && page_cards_all_marked_nonsticky(index);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@
|
|||
|
||||
#+gencgc
|
||||
(progn
|
||||
(defun page-words-used (index)
|
||||
(ash (slot (deref sb-vm::page-table index) 'sb-vm::words-used*) -1))
|
||||
(defun page-need-to-zero (index)
|
||||
(logbitp #+little-endian 6 #+big-endian 1
|
||||
(slot (deref sb-vm::page-table index) 'sb-vm::flags)))
|
||||
(oddp (slot (deref sb-vm::page-table index) 'sb-vm::words-used*)))
|
||||
(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))))
|
||||
|
|
@ -51,7 +52,7 @@
|
|||
(push index pages)
|
||||
(assert (= cons (+ base-address (* 2 sb-vm:n-word-bytes))))
|
||||
;; words-used should be 4, for 2 conses,
|
||||
(assert (= (slot (deref sb-vm::page-table index) 'sb-vm::words-used) 4))
|
||||
(assert (= (page-words-used index) 4))
|
||||
(dotimes (i (1- conses-per-page))
|
||||
(setq final (private-list (incf counter))))
|
||||
(assert (= final (+ base-address sb-vm:gencgc-page-bytes
|
||||
|
|
@ -70,7 +71,7 @@
|
|||
;; Each of the pages should have zero words used and need-to-zero = 1
|
||||
(dolist (index pages)
|
||||
(assert (page-need-to-zero index))
|
||||
(assert (= (slot (deref sb-vm::page-table index) 'sb-vm::words-used) 0))))))
|
||||
(assert (= (page-words-used index) 0))))))
|
||||
|
||||
#-gencgc
|
||||
(defun test-private-consing ()
|
||||
|
|
|
|||
Loading…
Reference in a new issue