Localize a macro
[sbcl.git] / src / compiler / generic / late-objdef.lisp
blob0609bc4dc480b36bc40148afa8f86f320a4b532b
1 ;;;; late machine-independent aspects of the object representation
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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.
12 (in-package "SB-VM")
14 #-c-headers-only
15 (macrolet ((frob ()
16 `(progn ,@*!late-primitive-object-forms*)))
17 (frob))
19 #+sb-thread
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))))
25 (progn
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).
38 #+sb-xc-host
39 (defparameter *scav/trans/size*
40 (mapcar
41 (lambda (entry)
42 (cons (symbol-value (symbolicate (car entry) "-WIDETAG"))
43 (cdr entry)))
44 `((bignum "bignum")
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.
56 (simple-fun "lose")
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")
67 (value-cell "boxed")
68 (symbol "symbol")
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")
72 (sap "unboxed")
73 (unbound-marker "immediate")
74 (weak-pointer "weakptr")
75 (instance "instance" "lose" "instance")
76 (fdefn "fdefn")
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"))))
123 #+sb-xc-host
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.
154 (dotimes (byte 256)
155 (when (or (eql 0 (logand byte fixnum-tag-mask))
156 (member (logand byte lowtag-mask)
157 `(,instance-pointer-lowtag
158 ,list-pointer-lowtag
159 ,fun-pointer-lowtag
160 ,other-pointer-lowtag))
161 (member byte `(#+64-bit ,single-float-widetag
162 ,character-widetag
163 ,unbound-marker-widetag)))
164 ;; gotta be a CONS
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)
174 (#.filler-widetag 0)
175 (t other-pointer-lowtag)))))))
176 (format stream "unsigned char widetag_lowtag[256] = {")
177 (dotimes (line 16)
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)))
186 (dotimes (i 256)
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"))))
195 (when pointer-kind
196 #-ppc64
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"))))))
202 #+ppc64
203 (progn
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)"
231 "scav_" scavtab)
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)"
235 "trans_" transtab)
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)"
240 "size_" sizetab)
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)
267 hidden
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
270 (token 0 :type word)
271 userdata
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.
277 (link 0))