1 ;;;; late machine-independent aspects of the object representation
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
16 `(progn ,@*!late-primitive-object-forms
*)))
20 (dovector (slot (primitive-object-slots (primitive-object 'thread
)))
21 (when (slot-special slot
)
22 (setf (info :variable
:wired-tls
(slot-special slot
))
23 (ash (slot-offset slot
) word-shift
))))
26 ;;; don't change allocation granularity
27 (assert (= gencgc-alloc-granularity
0))
28 ;;; cards are not larger than pages
29 (assert (<= gencgc-page-bytes
+backend-page-bytes
+))
30 ;;; largeness does not depend on the hardware page size
31 (defconstant large-object-size
#-mark-region-gc
(* 4 gencgc-page-bytes
)
32 #+mark-region-gc
(* 3/4 gencgc-page-bytes
))
33 (assert (integerp large-object-size
)))
35 ;;; Keep this (mostly) lined up with 'early-objdef' for sanity's sake!
36 ;;; The "transport" function is used only if the object is an OTHER-POINTER
37 ;;; (which goes through the dispatch table).
39 (defparameter *scav
/trans
/size
*
42 (cons (symbol-value (symbolicate (car entry
) "-WIDETAG"))
45 (ratio "boxed" "ratio_or_complex" "boxed")
46 (single-float ,(or #+64-bit
"immediate" "unboxed"))
47 (double-float "unboxed")
48 (complex-rational "boxed" "ratio_or_complex" "boxed")
49 (complex-single-float "unboxed")
50 (complex-double-float "unboxed")
52 (code-header "code_blob")
53 ;; For simple-fun, all three methods are "lose": "scav" is because you can't
54 ;; encounter a simple-fun in heap scanning; "trans" is because it's not an OTHER pointer,
55 ;; and "size" is because you can't take the size of a simple-fun by itself.
57 ;; The closure scavenge function needs to know if the "self" slot
58 ;; has pointer nature though it be fixnum tagged, as on x86.
59 ;; The sizer is short_boxed.
60 (closure ,(or #+(or x86 x86-64 arm64
) "closure" "short_boxed") "lose" "short_boxed")
61 ;; Like closure, but these can also have a layout pointer in the high header bytes.
62 (funcallable-instance "funinstance" "lose" "short_boxed")
63 ;; These have a scav and trans function, but no size function.
64 #-
(or x86 x86-64 arm64 riscv
)
65 (return-pc "return_pc_header" "return_pc_header" "lose")
69 ;; Can't transport characters as "other" pointer objects.
70 ;; It should be a cons cell half which would go through trans_list()
71 (character "immediate")
73 (unbound-marker "immediate")
74 (weak-pointer "weakptr")
75 (instance "instance" "lose" "instance")
78 #+sb-simd-pack
(simd-pack "unboxed")
79 #+sb-simd-pack-256
(simd-pack-256 "unboxed")
80 (filler "filler" "lose" "filler")
82 (simple-array "array")
83 (simple-array-unsigned-byte-2 "vector_unsigned_byte_2")
84 (simple-array-unsigned-byte-4 "vector_unsigned_byte_4")
85 (simple-array-unsigned-byte-7 "vector_unsigned_byte_8")
86 (simple-array-unsigned-byte-8 "vector_unsigned_byte_8")
87 (simple-array-unsigned-byte-15 "vector_unsigned_byte_16")
88 (simple-array-unsigned-byte-16 "vector_unsigned_byte_16")
89 (simple-array-unsigned-fixnum #-
64-bit
"vector_unsigned_byte_32"
90 #+64-bit
"vector_unsigned_byte_64")
91 (simple-array-unsigned-byte-31 "vector_unsigned_byte_32")
92 (simple-array-unsigned-byte-32 "vector_unsigned_byte_32")
93 #+64-bit
(simple-array-unsigned-byte-63 "vector_unsigned_byte_64")
94 #+64-bit
(simple-array-unsigned-byte-64 "vector_unsigned_byte_64")
96 (simple-array-signed-byte-8 "vector_unsigned_byte_8")
97 (simple-array-signed-byte-16 "vector_unsigned_byte_16")
98 (simple-array-signed-byte-32 "vector_unsigned_byte_32")
99 (simple-array-fixnum #-
64-bit
"vector_unsigned_byte_32"
100 #+64-bit
"vector_unsigned_byte_64")
101 #+64-bit
(simple-array-signed-byte-64 "vector_unsigned_byte_64")
103 (simple-array-single-float "vector_unsigned_byte_32")
104 (simple-array-double-float "vector_unsigned_byte_64")
105 (simple-array-complex-single-float "vector_unsigned_byte_64")
106 (simple-array-complex-double-float "vector_unsigned_byte_128")
108 (simple-bit-vector "vector_bit")
109 (simple-vector "vector_t")
111 (simple-array-nil "vector_nil")
112 (simple-base-string "base_string")
113 ;; UB32 works fine for character string, unless we decide to reimplement
114 ;; using 3 octets per code point.
115 #+sb-unicode
(simple-character-string "vector_unsigned_byte_32")
116 #+sb-unicode
(complex-character-string "array")
117 (complex-base-string "array")
119 (complex-bit-vector "array")
120 (complex-vector "array")
121 (complex-array "array"))))
124 (defun write-gc-tables (stream)
125 (format stream
"#include ~S~%" (sb-fasl::lispobj-dot-h
))
126 ;; Compute a bitmask of all specialized vector types,
127 ;; not including array headers, for maybe_adjust_large_object().
128 (let ((min #xff
) (bits 0))
129 (dovector (saetp *specialized-array-element-type-properties
*)
130 (unless (eq (saetp-primitive-type-name saetp
) 'simple-vector
)
131 (let ((widetag (saetp-typecode saetp
)))
132 (setf min
(min widetag min
)
133 bits
(logior bits
(ash 1 (ash widetag -
2)))))))
134 (format stream
"static inline int specialized_vector_widetag_p(unsigned char widetag) {
135 return widetag>=0x~X && (0x~8,'0XU >> ((widetag-0x80)>>2)) & 1;~%}~%"
136 min
(ldb (byte 32 32) bits
))
137 ;; Union in the bits for other unboxed object types.
138 (dolist (entry *scav
/trans
/size
*)
139 (when (member (second entry
) '("bignum" "unboxed" "filler") :test
'string
=)
140 (setf bits
(logior bits
(ash 1 (ash (car entry
) -
2))))))
141 (format stream
"static inline int leaf_obj_widetag_p(unsigned char widetag) {~%")
142 #+64-bit
(format stream
" return (0x~XLU >> (widetag>>2)) & 1;" bits
)
143 #-
64-bit
(format stream
" int bit = widetag>>2;
144 return (bit<32 ? 0x~XU >> bit : 0x~XU >> (bit-32)) & 1;"
145 (ldb (byte 32 0) bits
) (ldb (byte 32 32) bits
))
146 (format stream
"~%}~%"))
148 (format stream
"~%#ifdef WANT_SCAV_TRANS_SIZE_TABLES~%")
149 (let ((lowtag-tbl (make-array 256 :initial-element
0)))
150 ;; Build a table translating from the from low byte of first word of any
151 ;; heap object to that object's lowtag when pointed to by a tagged pointer.
152 ;; If the first word is {immediate | pointer} then the object is a cons,
153 ;; otherwise the object is a headered object.
155 (when (or (eql 0 (logand byte fixnum-tag-mask
))
156 (member (logand byte lowtag-mask
)
157 `(,instance-pointer-lowtag
160 ,other-pointer-lowtag
))
161 (member byte
`(#+64-bit
,single-float-widetag
163 ,unbound-marker-widetag
)))
165 (setf (svref lowtag-tbl byte
) list-pointer-lowtag
)))
166 (dolist (entry *scav
/trans
/size
*)
167 (destructuring-bind (widetag scav
&rest ignore
) entry
168 (declare (ignore ignore
))
169 (unless (string= scav
"immediate")
170 (setf (svref lowtag-tbl widetag
)
171 (+ #x80
(case widetag
172 (#.instance-widetag instance-pointer-lowtag
)
173 (#.
+function-widetags
+ fun-pointer-lowtag
)
175 (t other-pointer-lowtag
)))))))
176 (format stream
"unsigned char widetag_lowtag[256] = {")
178 (format stream
"~%~:{ ~:[0x~2,'0x~;~4d~],~}"
179 (mapcar (lambda (x) (list (member x
`(0 ,sb-vm
:list-pointer-lowtag
)) x
))
180 (coerce (subseq lowtag-tbl
(* line
16) (* (1+ line
) 16)) 'list
))))
181 (format stream
"~%};~%"))
182 (let ((scavtab (make-array 256 :initial-element nil
))
183 (ptrtab (make-list #+ppc64
16 #-ppc64
4))
184 (transtab (make-array 64 :initial-element nil
))
185 (sizetab (make-array 256 :initial-element nil
)))
187 (cond ((eql 0 (logand i fixnum-tag-mask
))
188 (setf (svref scavtab i
) "immediate" (svref sizetab i
) "immediate"))
190 (let ((pointer-kind (case (logand i lowtag-mask
)
191 (#.instance-pointer-lowtag
"instance")
192 (#.list-pointer-lowtag
"list")
193 (#.fun-pointer-lowtag
"fun")
194 (#.other-pointer-lowtag
"other"))))
197 (let ((n (ldb (byte 2 (- sb-vm
:n-lowtag-bits
2)) i
)))
198 (unless (nth n ptrtab
)
199 (setf (nth n ptrtab
) (format nil
"scav_~A_pointer" pointer-kind
))))
200 (setf (svref scavtab i
) (format nil
"~A_pointer" pointer-kind
)
201 (svref sizetab i
) "pointer"))))))
204 (fill ptrtab
"scav_lose")
205 (setf (aref scavtab
#xff
) "consfiller"
206 (aref sizetab
#xff
) "consfiller")
207 (setf (nth instance-pointer-lowtag ptrtab
) "scav_instance_pointer"
208 (nth list-pointer-lowtag ptrtab
) "scav_list_pointer"
209 (nth fun-pointer-lowtag ptrtab
) "scav_fun_pointer"
210 (nth other-pointer-lowtag ptrtab
) "scav_other_pointer"))
211 (dolist (entry *scav
/trans
/size
*)
212 (destructuring-bind (widetag scav
&optional
(trans scav
) (size trans
)) entry
213 ;; immediates use trans_lose which is what trans_immediate did anyway.
214 ;; Substitution here makes the *scav/trans/size* table definition
215 ;; more clear, because single-float is either immediate or unboxed,
216 ;; and it's not nice to repeat the reader conditional expressing that.
217 (when (string= trans
"immediate") (setq trans
"lose"))
218 (setf (svref scavtab widetag
) scav
219 (svref transtab
(ash widetag -
2)) trans
220 (svref sizetab widetag
) size
)))
221 (flet ((write-table (decl prefix contents
)
222 (format stream
"~A = {" decl
)
223 (loop for i from
0 for x across contents
224 when
(zerop (mod i
4))
225 do
(format stream
"~% ")
226 do
(format stream
"~V@<~A~A~:[~;,~]~>"
227 (if (= (mod i
4) 3) 0 31)
228 prefix
(or x
"lose") (< i
(length contents
))))
229 (format stream
"~%};~%")))
230 (write-table "sword_t (*const scavtab[256])(lispobj *where, lispobj object)"
232 (format stream
"static void (*scav_ptr[~d])(lispobj *where, lispobj object)~
233 = {~{~% (void(*)(lispobj*,lispobj))~A~^,~}~%};~%" (length ptrtab
) ptrtab
)
234 (write-table "static lispobj (*transother[64])(lispobj object)"
236 (format stream
"#define size_pointer (sizerfn)0~%")
237 (format stream
"#define size_immediate (sizerfn)0~%")
238 (format stream
"#define size_unboxed size_boxed~%")
239 (write-table "sword_t (*sizetab[256])(lispobj *where)"
241 (format stream
"#undef size_immediate~%")
242 (format stream
"#undef size_pointer~%")
243 (format stream
"#undef size_unboxed~%")))
244 (format stream
"#endif~%"))
246 (sb-xc:defstruct
(arena (:constructor nil
))
247 ;; Address of the 'struct arena_memblk' we're currently allocating to.
248 (current-block 0 :type word
)
249 ;; Address of the one mandatory 'struct arena_memblk' for this arena
250 (first-block 0 :type word
)
251 ;; Huge objects are those whose size exceeds a tiny fraction of the growth amount.
252 (huge-objects 0 :type word
)
253 ;; Arena allocation parameters
254 (original-size 0 :type word
)
255 (growth-amount 0 :type word
) ; additive
256 ;; Maximum we'll allow the arena to grow to, accounting for extension blocks
257 ;; and huge object blocks.
258 (size-limit 0 :type word
)
259 ;; Sum of sizes of currently allocated blocks
260 (length 0 :type word
)
261 ;; Sum of unusable bytes resulting from discarding the tail of the
262 ;; most recently claimed chunk when switching from the arena to the heap.
263 (bytes-wasted 0 :type word
)
264 ;; Small integer identifier starting from 0
265 (index 0 :type fixnum
)
266 ;; T if all memory has been protected with PROT_NONE (for debugging)
268 ;; a counter that increments on each rewind, and which can be used by a threads
269 ;; in a pool to detect that their cached TLAB pointers are invalid
272 ;; Link for global chain of all arenas, needed for GC when 'scavenge_arenas' is 1,
273 ;; so that GC can find all in-use arenas.
274 ;; This is a tagged pointer to the next arena in the chain, terminated by NIL.
275 ;; It is 0 until added to the global chain so we can tell the difference between
276 ;; an arena that was made but never used, and one that was used at some point.