1 ;;;; that part of DEFSTRUCT implementation which is needed not just
2 ;;;; in the target Lisp but also in the cross-compilation host
4 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
13 (in-package "SB-KERNEL")
15 (/show0
"code/defstruct.lisp 15")
19 ;;; Return the compiler layout for NAME. (The class referred to by
20 ;;; NAME must be a structure-like class.)
21 (defun compiler-layout-or-lose (name)
22 (let ((res (info :type
:compiler-layout name
)))
24 (error "Class is not yet defined or was undefined: ~S" name
))
25 ((not (typep (layout-%info res
) 'defstruct-description
))
26 (error "Class is not a structure class: ~S" name
))
28 (check-deprecated-type name
)
31 (defun compiler-layout-ready-p (name)
32 (let ((layout (info :type
:compiler-layout name
)))
33 (and layout
(typep (layout-%info layout
) 'defstruct-description
))))
35 (sb-xc:defmacro %make-structure-instance-macro
(dd slot-specs
&rest slot-vars
)
36 (if (compiler-layout-ready-p (dd-name dd
))
37 `(truly-the ,(dd-name dd
)
38 (%make-structure-instance
,dd
,slot-specs
,@slot-vars
))
39 ;; Non-toplevel defstructs don't have a layout at compile time,
40 ;; so we need to construct the actual function at runtime -- but
41 ;; we cache it at the call site, so that we don't perform quite
43 `(let* ((cell (load-time-value (list nil
)))
46 (funcall fun
,@slot-vars
)
47 (funcall (setf (car cell
)
48 (%make-structure-instance-allocator
,dd
,slot-specs
52 (sb-xc:defmacro %new-instance
(layout size
)
54 (i (truly-the ,(if (constantp layout
) (layout-classoid layout
) 'instance
)
55 (%make-instance
,size
))))
56 (%set-instance-layout i l
)
58 (sb-xc:defmacro %new-instance
* (layout len
)
60 ,(if (constantp layout
) (layout-classoid layout
) 'instance
)
61 (if (logtest (layout-flags ,layout
) sb-vm
::+strictly-boxed-flag
+)
63 (%make-instance
/mixed
,len
)))))
64 (%set-instance-layout i
,layout
)
67 (declaim (ftype (sfunction (defstruct-description list list
) function
)
68 %make-structure-instance-allocator
))
69 (defun %make-structure-instance-allocator
(dd slot-specs slot-vars
)
71 `(lambda ,(loop for var in slot-vars
72 collect
(if (consp var
)
75 (declare (optimize (sb-c:store-source-form
0)))
76 (%make-structure-instance-macro
,dd
',slot-specs
,@slot-vars
)))))
78 (defun %make-funcallable-structure-instance-allocator
(dd slot-specs
)
80 (bug "funcallable-structure-instance allocation with slots unimplemented"))
82 (compile nil
`(lambda ()
83 (declare (optimize (sb-c:store-source-form
0)))
84 (let ((object (%make-funcallable-instance
,(dd-length dd
))))
85 (setf (%fun-layout object
) ,(find-layout (dd-name dd
)))
88 ;;;; DEFSTRUCT-DESCRIPTION
90 ;;; The DEFSTRUCT-DESCRIPTION structure holds compile-time information
91 ;;; about a structure type.
92 ;;; Its definition occurs in 'early-classoid.lisp'
93 (defmethod print-object ((x defstruct-description
) stream
)
94 (print-unreadable-object (x stream
:type t
:identity t
)
95 (prin1 (dd-name x
) stream
)))
97 ;;; Does DD describe a structure with a class?
98 (defun dd-class-p (dd)
99 (if (member (dd-type dd
) '(structure funcallable-structure
)) t nil
))
100 (defmacro dd-named
(dd) `(logtest (dd-flags ,dd
) +dd-named
+))
101 (defmacro dd-pure
(dd) `(logtest (dd-flags ,dd
) +dd-pure
+))
102 (defmacro dd-null-lexenv-p
(dd) `(logtest (dd-flags ,dd
) +dd-nullenv
+))
103 (defun dd-print-option (dd)
104 (cond ((logtest (dd-flags dd
) +dd-printfun
+) :print-function
)
105 ((logtest (dd-flags dd
) +dd-printobj
+) :print-object
)))
107 (defun dd-layout-or-lose (dd)
108 (compiler-layout-or-lose (dd-name dd
)))
110 ;;;; DEFSTRUCT-SLOT-DESCRIPTION
112 ;;; A DEFSTRUCT-SLOT-DESCRIPTION holds compile-time information about
113 ;;; a structure slot. These objects are immutable.
114 (def!struct
(defstruct-slot-description
115 (:constructor make-dsd
(name type accessor-name bits default
))
119 (name nil
:read-only t
) ; name of slot
120 (type t
:read-only t
) ; declared type specifier
121 (accessor-name nil
:type symbol
:read-only t
) ; name of the accessor function
122 ;; Packed integer with 4 subfields.
123 ;; FIXNUM is ok for the host - it's guaranteed to be at least 16 signed bits
124 ;; and we don't have structures whose slot indices run into the thousands.
125 (bits 0 :type fixnum
)
126 (default nil
:read-only t
)) ; default value expression
127 (declaim (freeze-type defstruct-slot-description
))
129 (eval-when (:compile-toplevel
)
130 ;; Ensure that rsd-index is representable in 3 bits. (Can easily be changed)
131 (assert (<= (1+ (length *raw-slot-data
*)) 8)))
133 (defconstant sb-vm
:dsd-index-shift
8)
134 (defconstant sb-vm
:dsd-raw-type-mask
#b111
)
135 (defconstant dsd-default-error
(ash 1 7))
137 (defun pack-dsd-bits (index read-only safe-p always-boundp gc-ignorable rsd-index
)
138 (logior (ash index sb-vm
:dsd-index-shift
)
139 ;; (ash 1 7) meaning DEFAULT doesn't match TYPE is set during compilation of the constructor.
140 (if read-only
(ash 1 6) 0)
141 (if safe-p
(ash 1 5) 0)
142 (if always-boundp
(ash 1 4) 0)
143 (if gc-ignorable
(ash 1 3) 0)
144 (the (unsigned-byte 3) (if rsd-index
(1+ rsd-index
) 0))))
146 (declaim (inline dsd-always-boundp
149 ; dsd-read-only ; compilation order problem
152 ;;; In general we type-check a slot when it is written, not when read.
153 ;;; There are cases where we must check each read though:
155 ;;; (1) a structure subtype can constrain a slot type more highly than the
156 ;;; parent type constrains it. This requires that each read via the subtype's
157 ;;; accessor be type-checked, because a write via the parent writer may
158 ;;; store a value that does not satisfy the more restrictive constraint.
159 ;;; These slots have SAFE-P = 0 in the dsd.
160 ;;; (2) If a BOA constructor leaves an ordinary (non-raw) slot uninitialized,
161 ;;; then the slot contains the unbound-marker which can be tested with just
162 ;;; an EQ comparison. Such slots have ALWAYS-BOUNDP = 0 in the dsd.
163 ;;; This does not apply to raw slots, which can not hold an unbound marker.
165 ;;; Note that inheritance in the presence of a BOA constructor can cause
166 ;;; the parent structure's notion of ALWAYS-BOUNDP to be wrong.
167 ;;; We don't try to deal with that.
168 ;;; FIXME: We could emit a style-warning if this happens, and/or if any code
169 ;;; was compiled under the assumption that the slot was safe.
171 ;;; Further note that MAKE-LOAD-FORM methods can do damage to type invariants
172 ;;; without any efficient means of detection, if MAKE-LOAD-FORM-SAVING-SLOTS
173 ;;; is used without specifying all slots.
175 ;; Index into *RAW-SLOT-DATA* vector of the RAW-SLOT-DATA for this slot.
176 ;; The index is NIL if this slot is not raw.
177 (defun dsd-rsd-index (dsd)
178 (let ((val (logand (dsd-bits dsd
) sb-vm
:dsd-raw-type-mask
)))
179 (if (plusp val
) (the (mod #.
(length *raw-slot-data
*)) (1- val
)))))
180 ;;; GC-ignorable slots are a superset of raw slots.
181 (defun dsd-gc-ignorable (dsd) (logbitp 3 (dsd-bits dsd
)))
183 ;; Whether the slot is always bound. Slots are almost always bound,
184 ;; the exception being those which appear as an &AUX var with no value
185 ;; in a BOA constructor.
186 (defun dsd-always-boundp (dsd) (logbitp 4 (dsd-bits dsd
)))
187 ;; Whether the slot is known to be always of the specified type
188 ;; A slot may be SAFE-P even if not always-boundp.
189 (defun dsd-safe-p (dsd) (logbitp 5 (dsd-bits dsd
)))
190 (defun dsd-read-only (dsd) (logbitp 6 (dsd-bits dsd
)))
191 ;; its position in the implementation sequence
192 (defun dsd-index (dsd)
193 (the index
(ash (dsd-bits dsd
) (- sb-vm
:dsd-index-shift
))))
194 (sb-c:define-source-transform dsd-index
(dsd)
195 `(truly-the index
(ash (dsd-bits ,dsd
) ,(- sb-vm
:dsd-index-shift
))))
197 (!set-load-form-method defstruct-slot-description
(:host
:xc
:target
))
198 (defmethod print-object ((x defstruct-slot-description
) stream
)
199 (print-unreadable-object (x stream
:type t
)
200 (prin1 (dsd-name x
) stream
)))
202 (defun dsd-raw-slot-data (dsd)
203 (let ((rsd-index (dsd-rsd-index dsd
)))
205 (svref *raw-slot-data
* rsd-index
))))
207 (defun dsd-raw-type (dsd)
208 (acond ((dsd-raw-slot-data dsd
) (raw-slot-data-raw-type it
))
211 (defun dsd-reader (dsd funinstancep
)
212 (acond ((dsd-raw-slot-data dsd
)
213 (values (raw-slot-data-reader-name it
) (raw-slot-data-writer-name it
)))
215 (values '%funcallable-instance-info
'%set-funcallable-instance-info
))
217 (values '%instance-ref
'%instance-set
))))
219 ;;;; typed (non-class) structures
221 ;;; Return a type specifier we can use for testing :TYPE'd structures.
222 (defun dd-lisp-type (defstruct)
223 (ecase (dd-type defstruct
)
225 (vector `(simple-array ,(dd-%element-type defstruct
) (*)))))
227 ;;;; shared machinery for inline and out-of-line slot accessor functions
229 ;;; Classic comment preserved for entertainment value:
231 ;;; "A lie can travel halfway round the world while the truth is
232 ;;; putting on its shoes." -- Mark Twain
234 ;;;; the legendary DEFSTRUCT macro itself (both CL:DEFSTRUCT and its
235 ;;;; close personal friend SB-XC:DEFSTRUCT)
237 (defun %defstruct-package-locks
(dd)
238 (declare (ignorable dd
))
240 (let ((name (dd-name dd
)))
241 (with-single-package-locked-error
242 (:symbol name
"defining ~S as a structure"))
243 (awhen (dd-predicate-name dd
)
244 (with-single-package-locked-error
245 (:symbol it
"defining ~s as a predicate for ~s structure" name
)))
246 (awhen (dd-copier-name dd
)
247 (with-single-package-locked-error
248 (:symbol it
"defining ~s as a copier for ~s structure" name
)))
249 (dolist (ctor (dd-constructors dd
))
250 (with-single-package-locked-error
251 (:symbol
(car ctor
) "defining ~s as a constructor for ~s structure" name
)))
252 (dolist (dsd (dd-slots dd
))
253 (awhen (dsd-accessor-name dsd
)
254 (with-single-package-locked-error
255 (:symbol it
"defining ~s as an accessor for ~s structure" name
))))))
257 ;;; Since DSDs live a long time for inheritance purposes don't attach
258 ;;; the source form to them directly.
259 (defvar *dsd-source-form
*)
261 (defun accessor-definitions (dd defuns
)
263 ;; Return the ordinary toplevel (usually, anyway) defuns
264 (loop for dsd in
(dd-slots dd
)
265 for accessor-name
= (dsd-accessor-name dsd
)
266 unless
(accessor-inherited-data accessor-name dd
)
267 nconc
(dx-let ((key (cons dd dsd
)))
268 (let ((source-form (and (boundp '*dsd-source-form
*)
269 (cdr (assq dsd
*dsd-source-form
*)))))
270 `(,@(unless (dsd-read-only dsd
)
271 `((sb-c:xdefun
(setf ,accessor-name
) :accessor
,source-form
(value instance
)
272 ,(slot-access-transform :setf
'(instance value
) key
))))
273 (sb-c:xdefun
,accessor-name
:accessor
,source-form
(instance)
274 ,(slot-access-transform :read
'(instance) key
))))))
275 ;; Return fragements of code that CLOS can use. We don't return
276 ;; the toplevel DEFUNs because those generally perform an
277 ;; unneeded type-check unless in safety 0. These CLOS-related
278 ;; lambdas don't need to check the type of the instance because
279 ;; it was already subject to type-based dispatch, and must let
280 ;; unbound markers through for the CLOS machinery to handle.
282 ;; FIXME: it seems like all these fragments should be packed
283 ;; into a single codebob which will have less overhead than
284 ;; separate blobs. Afaict, the only way to do that is to return
285 ;; one lambda that returns all the lambdas.
287 (dolist (dsd (dd-slots dd
) (result))
288 (binding* ((key (cons dd dsd
))
289 (name (string (dsd-name dsd
))) ; anonymize by stringification
290 ;; reader and writer are the primitive operations
291 ((reader writer
) (dsd-reader dsd
(neq (dd-type dd
) 'structure
)))
292 ;; accessor is the global defun
293 (accessor (dsd-accessor-name dsd
)))
294 (declare (dynamic-extent key
))
295 (result (if (or (dsd-read-only dsd
) (not (dsd-always-boundp dsd
)))
296 `(named-lambda (setf ,name
) (#1=#:v
#2=#:x
)
297 ,@(if (eql (dsd-type dsd
) 't
)
299 `((,writer
(truly-the ,(dd-name dd
) #2#) ,(dsd-index dsd
) #1#) #1#)
300 `(,(slot-access-transform :setf
`(#1# (truly-the ,(dd-name dd
) #2#))
303 (if (not (dsd-always-boundp dsd
))
304 `(named-lambda ,name
(#2#)
305 ,(if (dsd-safe-p dsd
)
306 ;; Most slots are safe-p (type-safe for reading),
307 ;; so we can be concise rather than use SLOT-ACCESS-TRANSFORM
308 ;; plus a rebinding of X with TRULY-THE.
309 `(,reader
(truly-the ,(dd-name dd
) #2#) ,(dsd-index dsd
))
310 ;; Don't check X, but do check the the fetched value.
311 (slot-access-transform :read
`((truly-the ,(dd-name dd
) #2#))
315 ;;; shared logic for host macroexpansion for SB-XC:DEFSTRUCT and
316 ;;; cross-compiler macroexpansion for CL:DEFSTRUCT
317 ;;; This monster has exactly one inline use in the final image,
318 ;;; and we can drop the definition.
320 ;;; The DELAYP argument deserves some explanation - Because :COMPILE-TOPLEVEL effects
321 ;;; of non-toplevel DEFSTRUCT forms don't happen, the compiler is unable to produce
322 ;;; good accessor code. By delaying compilation until the DEFSTRUCT happens, whenever
323 ;;; or if ever that may be, we can produce better code. DELAY, if true, says to defer
324 ;;; compilation, ignoring the original lexical environment. This approach produces a
325 ;;; nicer expansion in general, versus macroexpanding to yet another macro whose sole
326 ;;; purpose is to sense that earlier compile-time effects have happened.
328 ;;; Some caveats: (1) a non-toplevel defstruct compiled after already seeing
329 ;;; the same, due to repeated compilation of a file perhaps, will use the known
330 ;;; definition, since technically structures must not be incompatibly redefined.
331 ;;; (2) delayed DEFUNS don't get the right TLF index in their debug info.
332 ;;; We could expand into the internal expansion of DEFUN with an extra argument
333 ;;; for the source location, which would get whatever "here" is instead of random.
334 ;;; In other words: `(progn (sb-impl::%defun struct-slot (...) ... ,(source-location))
335 ;;; and then use that to stuff in the correct info at delayed-compile time.
337 ;;; Note also that sb-fasteval has some hairy logic to JIT-compile slot accessors.
338 ;;; It might be a lot nicer to pull out that junk, and have this expander know that
339 ;;; it is producing code for fasteval, and explicitly compile much the same way
340 ;;; that delayed accessor compilation happens. Here's a REPL session:
341 ;;; * (defstruct foo val) => FOO
342 ;;; * #'foo-val => #<INTERPRETED-FUNCTION FOO-VAL>
343 ;;; * (defun foovalx (afoo) (* (foo-val afoo) 2)) => FOOVALX
344 ;;; * (foovalx (make-foo :val 9)) => 18
345 ;;; * #'foo-val => #<FUNCTION FOO-VAL>
346 ;;; So FOO-VAL got compiled on demand.
348 (declaim (inline !expander-for-defstruct
))
349 (defun !expander-for-defstruct
(null-env-p optimize-speed delayp name-and-options
350 slot-descriptions expanding-into-code-for
)
353 (if (listp name-and-options
)
354 (values (car name-and-options
) (cdr name-and-options
))
355 (values name-and-options nil
)))
356 ((nil) (unless (symbolp name
)
357 ;; Rather than hit MAKE-DEFSTRUCT-DESCRIPTION's type-check
358 ;; on the NAME slot, we can be a little more clear.
359 (error "DEFSTRUCT: ~S is not a symbol." name
)))
360 (flagbits (logior #+sb-xc-host
(if (eq name
'layout
) +dd-varylen
+ 0)
361 (if null-env-p
+dd-nullenv
+ 0)))
362 (dd (make-defstruct-description name flagbits
))
363 (*dsd-source-form
* nil
)
364 ((inherits comparators
) (parse-defstruct dd options slot-descriptions
))
365 (constructor-definitions
366 (mapcar (lambda (ctor)
367 `(sb-c:xdefun
,(car ctor
)
370 ,@(structure-ctor-lambda-parts dd
(cdr ctor
))))
371 (dd-constructors dd
)))
373 (when (dd-print-option dd
)
374 (let* ((x (make-symbol "OBJECT"))
375 (s (make-symbol "STREAM"))
376 (fname (dd-printer-fname dd
))
377 (depthp (eq (dd-print-option dd
) :print-function
)))
378 ;; Giving empty :PRINT-OBJECT or :PRINT-FUNCTION options
379 ;; leaves FNAME eq to NIL. The user-level effect is
380 ;; to generate a PRINT-OBJECT method specialized for the type,
381 ;; implementing the default #S structure-printing behavior.
383 (setf fname
'default-structure-print depthp t
))
384 ((not (symbolp fname
))
385 ;; Don't dump the source form into the DD constant;
386 ;; just indicate that there was an expression there.
387 (setf (dd-printer-fname dd
) 'lambda
)))
388 `((defmethod print-object ((,x
,name
) ,s
)
389 (funcall #',fname
,x
,s
390 ,@(if depthp
`(*current-level-in-print
*)))))))))
391 ;; Return a list of forms
393 `(,@(when (eq expanding-into-code-for
:target
)
394 ;; Note we intentionally enforce package locks, calling
395 ;; %DEFSTRUCT first. %DEFSTRUCT has the tests (and resulting
396 ;; CERROR) for collisions with LAYOUTs which already exist in
397 ;; the runtime. If there are collisions, we want the user's
398 ;; response to CERROR to control what happens. If the ABORT
399 ;; restart is chosen, %COMPILER-DEFSTRUCT should not modify
400 ;; the definition the class.
401 `((eval-when (:compile-toplevel
:load-toplevel
:execute
)
402 (%defstruct-package-locks
',dd
))))
403 (%defstruct
',dd
',inherits
(sb-c:source-location
))
404 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
405 (%compiler-defstruct
',dd
',inherits
))
406 ,@(when (eq expanding-into-code-for
:target
)
408 `(,@(awhen (dd-copier-name dd
)
409 `((sb-c:xdefun
,(dd-copier-name dd
) :copier nil
(instance)
410 (copy-structure (the ,(dd-name dd
) instance
)))))
411 ,@(awhen (dd-predicate-name dd
)
412 `((sb-c:xdefun
,(dd-predicate-name dd
) :predicate nil
(object)
413 (typep object
',(dd-name dd
)))))
414 ,@(accessor-definitions dd t
))))
415 (if (and delayp
(not (compiler-layout-ready-p name
)))
416 `((sb-impl::%simple-eval
',(cons 'progn defuns
)
419 ;; This must be in the same lexical environment
420 ,@constructor-definitions
422 ;; Various other operations only make sense on the target SBCL.
423 ;; %TARGET-DEFSTRUCT returns NAME
424 (%target-defstruct
',dd
426 (gen-custom-equalp dd comparators
))
427 ,@(accessor-definitions dd nil
)))))
429 ;; FIXME: missing package lock checks
430 `((eval-when (:compile-toplevel
:load-toplevel
:execute
)
431 (%proclaim-defstruct-ctors
',dd
)
432 (setf (info :typed-structure
:info
',name
) ',dd
))
433 (setf (info :source-location
:typed-structure
',name
)
434 (sb-c:source-location
))
435 ,@(when (eq expanding-into-code-for
:target
)
436 `(,@(typed-accessor-definitions dd
)
437 ,@(typed-predicate-definitions dd
)
438 ,@(typed-copier-definitions dd
)
439 ,@constructor-definitions
441 `((setf (documentation ',(dd-name dd
) 'structure
)
445 (defun gen-custom-equalp (dd comparators
)
446 ;; Process the easiest slots first.
447 ;; TODO: consecutive word-sized slots should try to use instructions
448 ;; that compare more than one word at a time.
449 (collect ((group1) (group2) (group3))
450 (mapc (lambda (dsd comparator
)
451 (let ((x `(truly-the ,(dsd-type dsd
) (,(dsd-reader dsd nil
) a
,(dsd-index dsd
))))
452 (y `(truly-the ,(dsd-type dsd
) (,(dsd-reader dsd nil
) b
,(dsd-index dsd
)))))
453 (cond ((member comparator
'(= char-equal
))
454 (group1 `(,comparator
,x
,y
))) ; bounded amount of testing
455 ((member comparator
'(bit-vector-=))
456 ;; unbounded but not recursive. Try EQ first though
458 `((lambda (x y
) (or (eq x y
) (bit-vector-= x y
))) ,x
,y
)))
460 (group3 `(,comparator
,x
,y
)))))) ; recursive
463 ;; use a string for the name since it's not a global function
464 `(named-lambda ,(format nil
"~A-EQUALP" (dd-name dd
)) (a b
)
465 (declare (optimize (sb-c:store-source-form
0) (safety 0)) (type ,(dd-name dd
) a b
)
466 (ignorable a b
)) ; if zero slots
467 (and ,@(group1) ,@(group2) ,@(group3)))))
471 ;; When compiling and loading the cross-compiler, SB-XC:DEFSTRUCT gets
472 ;; a bootstrap definition from src/code/defbangstruct.
473 ;; The old definition has to be uninstalled to avoid a redefinition warning here.
474 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
475 (fmakunbound 'sb-xc
:defstruct
))
476 (defmacro sb-xc
:defstruct
(name-and-options &rest slot-descriptions
)
477 "Cause information about a target structure to be built into the
479 `(progn ,@(!expander-for-defstruct
480 t nil nil name-and-options slot-descriptions
:host
))))
482 (sb-xc:defmacro defstruct
(name-and-options &rest slot-descriptions
484 "DEFSTRUCT {Name | (Name Option*)} [Documentation] {Slot | (Slot [Default] {Key Value}*)}
485 Define the structure type Name. Instances are created by MAKE-<name>,
486 which takes &KEY arguments allowing initial slot values to the specified.
487 A SETF'able function <name>-<slot> is defined for each slot to read and
488 write slot values. <name>-p is a type predicate.
490 Popular DEFSTRUCT options (see manual for others):
494 Specify the name for the constructor or predicate.
496 (:CONSTRUCTOR Name Lambda-List)
497 Specify the name and arguments for a BOA constructor
498 (which is more efficient when keyword syntax isn't necessary.)
500 (:INCLUDE Supertype Slot-Spec*)
501 Make this type a subtype of the structure type Supertype. The optional
502 Slot-Specs override inherited slot options.
507 Asserts that the value of this slot is always of the specified type.
510 If true, no setter function is defined for this slot."
513 (sb-kernel:lexenv
(sb-c::null-lexenv-p env
))
514 ;; a LOCALLY environment would be fine,
515 ;; but is not an important case to handle.
516 #+sb-fasteval
(sb-interpreter:basic-env nil
)
518 ;; Decide whether the expansion should delay reference
519 ;; to this structure type. (See explanation up above).
520 ;; This is about performance, not semantics. Non-toplevel
521 ;; effects happen when they should even if this were to
522 ;; produce the preferred expansion for toplevel.
523 (delayp (not (or *top-level-form-p
* null-env-p
)))
525 (and (not delayp
) (sb-c:policy env
(< space
3)))))
527 ,@(!expander-for-defstruct null-env-p optimize-speed delayp
528 name-and-options slot-descriptions
531 ;;;; functions to generate code for various parts of DEFSTRUCT definitions
533 ;;; First, a helper to determine whether a name names an inherited
535 (defun accessor-inherited-data (name defstruct
)
536 (assoc name
(dd-inherited-accessor-alist defstruct
) :test
#'eq
))
538 ;;; Return a list of forms which create a predicate function for a
540 (defun typed-predicate-definitions (defstruct)
541 (let ((name (dd-name defstruct
))
542 (predicate-name (dd-predicate-name defstruct
))
543 (argname 'x
)) ; KISS: no user code appears in the DEFUN
545 (aver (dd-named defstruct
))
546 (let ((ltype (dd-lisp-type defstruct
))
547 (name-index (cdr (car (last (find-name-indices defstruct
))))))
548 `((defun ,predicate-name
(,argname
)
549 (and (typep ,argname
',ltype
)
551 ((subtypep ltype
'list
)
552 `(do ((head (the ,ltype
,argname
) (cdr head
))
554 ((or (not (consp head
)) (= i
,name-index
))
555 (and (consp head
) (eq ',name
(car head
))))))
556 ((subtypep ltype
'vector
)
557 `(and (>= (length (the ,ltype
,argname
))
558 ,(dd-length defstruct
))
559 (eq ',name
(aref (the ,ltype
,argname
) ,name-index
))))
560 (t (bug "Unhandled representation type in typed DEFSTRUCT: ~
561 ~/sb-impl:print-type-specifier/."
564 ;;; Return a list of forms to create a copier function of a typed DEFSTRUCT.
565 (defun typed-copier-definitions (defstruct)
566 (when (dd-copier-name defstruct
)
567 `((setf (fdefinition ',(dd-copier-name defstruct
)) #'copy-seq
)
568 (declaim (ftype function
,(dd-copier-name defstruct
))))))
570 ;;; Return a list of function definitions for accessing and setting
571 ;;; the slots of a typed DEFSTRUCT. The functions are proclaimed to be
572 ;;; inline, and the types of their arguments and results are declared
573 ;;; as well. We count on the compiler to do clever things with ELT.
574 (defun typed-accessor-definitions (defstruct)
576 (let ((ltype (dd-lisp-type defstruct
)))
577 (dolist (slot (dd-slots defstruct
))
578 (let ((name (dsd-accessor-name slot
))
579 (index (dsd-index slot
))
581 (structure '(structure))
582 (slot-type `(and ,(dsd-type slot
)
583 ,(dd-%element-type defstruct
))))
584 (let ((inherited (accessor-inherited-data name defstruct
)))
587 (stuff `(declaim (inline ,name
,@(unless (dsd-read-only slot
)
589 (stuff `(defun ,name
,structure
590 (declare (type ,ltype .
,structure
))
591 (the ,slot-type
(elt ,(car structure
) ,index
))))
592 (unless (dsd-read-only slot
)
594 `(defun (setf ,name
) (,(car new-value
) .
,structure
)
595 (declare (type ,ltype .
,structure
) (type ,slot-type .
,new-value
))
596 (setf (elt ,(car structure
) ,index
) .
,new-value
)))))
597 ((not (= (cdr inherited
) index
))
598 (style-warn "~@<Non-overwritten accessor ~S does not access ~
599 slot with name ~S (accessing an inherited slot ~
600 instead).~:@>" name
(dsd-name slot
))))))))
606 ;;; A defstruct option can be either a keyword or a list of a keyword
607 ;;; and arguments for that keyword; specifying the keyword by itself is
608 ;;; equivalent to specifying a list consisting of the keyword
609 ;;; and no arguments.
610 ;;; It is unclear whether that is meant to imply that any of the keywords
611 ;;; may be present in their atom form, or only if the grammar at the top
612 ;;; shows the atom form does <atom> have the meaning of (<atom>).
613 ;;; At least one other implementation accepts :NAMED as a singleton list.
614 ;; We take a more rigid view that the depicted grammar is exhaustive.
616 (defconstant-eqx +dd-option-names
+
617 ;; Each keyword, except :CONSTRUCTOR which may appear more than once,
618 ;; and :NAMED which is trivial, and unambiguous if present more than
619 ;; once, though possibly worth a style-warning.
620 #(:include
; at least 1 argument
621 :initial-offset
; exactly 1 argument
622 :pure
; exactly 1 argument [nonstandard]
623 :type
; exactly 1 argument
624 :conc-name
; 0 or 1 arg
631 ;;; Parse a single DEFSTRUCT option and store the results in DD.
632 (defun parse-1-dd-option (option dd seen-options
)
633 (declare (type (unsigned-byte #.
(length +dd-option-names
+)) seen-options
))
634 (let* ((keyword (first option
))
635 (bit (position keyword
+dd-option-names
+))
638 (arg (if arg-p
(car args
)))
640 (declare (type (unsigned-byte 9) seen-options
)) ; mask over DD-OPTION-NAMES
642 (if (logbitp bit seen-options
)
643 (error "More than one ~S option is not allowed" keyword
)
644 (setf seen-options
(logior seen-options
(ash 1 bit
))))
645 (multiple-value-bind (syntax-group winp
)
646 (cond ; Perform checking per comment at +DD-OPTION-NAMES+.
647 ((= bit
0) (values 0 (and arg-p
(proper-list-p args
)))) ; >1 arg
648 ((< bit
4) (values 1 (and arg-p
(not (cdr args
))))) ; exactly 1
649 (t (values 2 (or (not args
) (singleton-p args
))))) ; 0 or 1
651 (if (proper-list-p option
)
652 (error "DEFSTRUCT option ~S ~[requires at least~;~
653 requires exactly~;accepts at most~] one argument" keyword syntax-group
)
654 (error "Invalid syntax in DEFSTRUCT option ~S" option
)))))
657 ;; unlike (:predicate) and (:copier) which mean "yes" if supplied
658 ;; without their argument, (:conc-name) and :conc-name mean no conc-name.
659 ;; Also note a subtle difference in :conc-name "" vs :conc-name NIL.
660 ;; The former re-interns each slot name into *PACKAGE* which might
661 ;; not be the same as using the given name directly as an accessor.
662 (setf (dd-conc-name dd
) (if arg
(string arg
))))
663 (:constructor
; takes 0 to 2 arguments.
664 (destructuring-bind (&optional
(cname (symbolicate "MAKE-" name
))
665 (lambda-list nil ll-supplied-p
)) args
668 ;; Implementations disagree on the meaning of
669 ;; (:CONSTRUCTOR NIL (A B C)).
670 ;; The choices seem to be: don't define a constructor,
671 ;; define a constructor named NIL, signal a user error,
672 ;; or crash the system itself. The spec implies
673 ;; the behavior that we have, but at least a
674 ;; style-warning seems appropriate.
676 (style-warn "~S does not define a constructor" option
)))
677 ((not ll-supplied-p
) :default
)
681 (declare (dynamic-extent x
))
682 (subseq x
0 ; remove trailing NILs
683 (1+ (position-if #'identity x
:from-end t
))))
686 :accept
(lambda-list-keyword-mask
687 '(&optional
&rest
&key
&allow-other-keys
&aux
))
689 (dd-constructors dd
) ; preserve order, just because
690 (nconc (dd-constructors dd
) (list (cons cname lambda-list
))))))
692 (setf (dd-copier-name dd
) (if arg-p arg
(symbolicate "COPY-" name
))))
694 (setf (dd-predicate-name dd
) (if arg-p arg
(symbolicate name
"-P"))))
696 (setf (dd-include dd
) args
))
697 ((:print-function
:print-object
)
698 (when (dd-print-option dd
)
699 (error "~S and ~S may not both be specified"
700 (dd-print-option dd
) keyword
))
701 (setf (dd-flags dd
) (logior (if (eq keyword
:print-object
) +dd-printobj
+ +dd-printfun
+)
703 (dd-printer-fname dd
) arg
))
705 (cond ((member arg
'(list vector
))
706 (setf (dd-type dd
) arg
(dd-%element-type dd
) t
))
707 ((and (listp arg
) (eq (first arg
) 'vector
))
708 ;; The spec is self-contradictory about this!
710 ;; type-option::= (:type type)
711 ;; type --- one of the type specifiers list, vector, or (vector size),
712 ;; or some other type specifier defined by the implementation to be appropriate.
713 ;; However the description of the keyword makes it pretty clear that
714 ;; the option's syntax is (vector /element-type/).
715 ;; I'm not sure if it's valid to specify (VECTOR *) as the representation.
716 ;; CLISP thinks it is not, but only signals an error when the constructor
717 ;; is called. So at minimum it's unportable, if not illegal.
718 (destructuring-bind (elt-type) (cdr arg
)
719 (setf (dd-type dd
) 'vector
(dd-%element-type dd
) elt-type
)))
721 (error "~S is a bad :TYPE for DEFSTRUCT." arg
))))
723 (error "The DEFSTRUCT option :NAMED takes no arguments."))
725 (setf (dd-offset dd
) arg
)) ; FIXME: disallow (:INITIAL-OFFSET NIL)
727 (setf (dd-flags dd
) (logior (logandc2 (dd-flags dd
) +dd-pure
+)
728 (if arg
+dd-pure
+ 0))))
730 (error "unknown DEFSTRUCT option:~% ~S" option
)))
733 ;;; Parse OPTIONS into the given DD.
734 (defun parse-defstruct-options (options dd
)
735 (let ((seen-options 0)
737 (declare (type (unsigned-byte #.
(length +dd-option-names
+)) seen-options
))
738 (dolist (option options
)
739 (if (eq option
:named
)
741 (dd-flags dd
) (logior (dd-flags dd
) +dd-named
+))
744 (cond ((consp option
) option
)
746 '(:conc-name
:constructor
:copier
:predicate
))
749 ;; FIXME: ugly message (defstruct (s :include) a)
750 ;; saying "unrecognized" when it means "bad syntax"
751 (error "unrecognized DEFSTRUCT option: ~S" option
)))
756 (error ":OFFSET can't be specified unless :TYPE is specified."))
757 #-compact-instance-header
758 (unless (dd-include dd
)
759 ;; FIXME: It'd be cleaner to treat no-:INCLUDE as defaulting
760 ;; to :INCLUDE STRUCTURE-OBJECT, and then let the general-case
761 ;; (INCF (DD-LENGTH DD) (DD-LENGTH included-DD)) logic take
762 ;; care of this. (Except that the :TYPE VECTOR and :TYPE
763 ;; LIST cases, with their :NAMED and un-:NAMED flavors,
764 ;; make that messy, alas.)
765 (incf (dd-length dd
))))
767 ;; In case we are here, :TYPE is specified.
769 ;; CLHS - "The structure can be :named only if the type SYMBOL
770 ;; is a subtype of the supplied element-type."
771 (multiple-value-bind (winp certainp
)
772 (subtypep 'symbol
(dd-%element-type dd
))
773 (when (and (not winp
) certainp
)
774 (error ":NAMED option is incompatible with element ~
775 type ~/sb-impl:print-type-specifier/"
776 (dd-%element-type dd
))))
777 (when (dd-predicate-name dd
)
778 (error ":PREDICATE cannot be used with :TYPE ~
779 unless :NAMED is also specified.")))
780 (awhen (dd-print-option dd
)
781 (error ":TYPE option precludes specification of ~S option" it
))
783 (incf (dd-length dd
)))
784 (let ((offset (dd-offset dd
)))
785 (when offset
(incf (dd-length dd
) offset
)))))
787 (let ((name (dd-name dd
)))
788 (collect ((keyword-ctors) (boa-ctors))
789 (let (no-constructors)
790 (dolist (constructor (dd-constructors dd
))
791 (destructuring-bind (ctor-name . ll
) constructor
792 (cond ((not ctor-name
) (setq no-constructors t
))
793 ((eq ll
:default
) (keyword-ctors constructor
))
794 (t (boa-ctors constructor
)))))
795 ;; Remove (NIL) and sort so that BOA constructors are last.
796 (setf (dd-constructors dd
)
799 (when (or (keyword-ctors) (boa-ctors))
800 (error "(:CONSTRUCTOR NIL) combined with other :CONSTRUCTORs"))
802 (append (or (keyword-ctors)
804 `((,(symbolicate "MAKE-" name
) .
:default
))))
807 ;; POSITION is constant-foldable, but folding happens _after_ transforming to
808 ;; a CASE expression which is surprising. CASE could invoke either POINTERP
809 ;; or NON-NULL-SYMBOL-P would would need to be emulated in the cross-compiler.
810 ;; That's easy to do, but it's even easier to reduce to a constant via macro
811 ;; as it doesn't require the extra support functions.
812 (macrolet ((option-present-p (bit-name)
813 `(logbitp ,(position bit-name
+dd-option-names
+) seen-options
)))
814 (when (and (not (option-present-p :predicate
))
815 (or (dd-class-p dd
) named-p
))
816 (setf (dd-predicate-name dd
) (symbolicate name
"-P")))
817 (unless (option-present-p :conc-name
)
818 (setf (dd-conc-name dd
) (string (gensymify* name
"-"))))
819 (unless (option-present-p :copier
)
820 (setf (dd-copier-name dd
) (symbolicate "COPY-" name
)))))
823 ;;; Given name and options and slot descriptions (and possibly doc
824 ;;; string at the head of slot descriptions) return a DD holding that
826 (defun parse-defstruct (dd options slot-descriptions
)
827 (declare (type defstruct-description dd
))
828 (let* ((option-bits (parse-defstruct-options options dd
))
831 #+sb-xc-host
(!inherits-for-structure dd
)
833 (let ((super (compiler-layout-or-lose (or (first (dd-include dd
))
834 'structure-object
))))
835 (concatenate 'simple-vector
836 (layout-inherits super
) (vector super
)))))
839 ;; The classoid needs a layout whereby to convey inheritance.
840 ;; Classoids only store a *direct* superclass list.
841 ;; Both the layout and classoid are throwaway objects.
842 ;; It's probably too dangerous to stack-allocate, because references
843 ;; could leak from the type cache machinery.
844 (let* ((classoid (make-structure-classoid :name
(dd-name dd
)))
845 (layout (make-temporary-layout (hash-layout-name (dd-name dd
))
847 (setf (classoid-layout classoid
) layout
)
849 (ancestor-slot-comparator-list))
851 (when (member (dd-name dd
) '(pathname logical-pathname
))
852 (setf (dd-alternate-metaclass dd
) '(t built-in-classoid nil
)))
853 ;; Type parsing should be done assuming that prototype classoid
854 ;; exists, which fixes a problem when redefining a DEFTYPE which
855 ;; appeared to be a raw slot. e.g.
856 ;; (DEFTYPE X () 'SINGLE-FLOAT) and later (DEFSTRUCT X (A 0 :TYPE X)).
857 ;; This is probably undefined behavior, but at least we'll not crash.
858 ;; Also make self-referential definitions not signal PARSE-UNKNOWN-TYPE
859 ;; on slots whose :TYPE option allows an instance of itself
860 (when (dd-include dd
)
861 (setq ancestor-slot-comparator-list
862 (frob-dd-inclusion-stuff proto-classoid dd option-bits
)))
863 (when (stringp (car slot-descriptions
))
864 (setf (dd-doc dd
) (pop slot-descriptions
)))
865 (collect ((comparator-list ancestor-slot-comparator-list
))
866 (dolist (slot-description slot-descriptions
)
868 (nth-value 1 (parse-1-dsd proto-classoid dd slot-description
))))
869 (comparator-list comparator
)))
870 (when (dd-class-p dd
)
871 (multiple-value-bind (bitmap any-raw
) (calculate-dd-bitmap dd
)
872 (when any-raw
(setf (dd-%element-type dd
) '*))
873 (setf (dd-bitmap dd
) bitmap
)))
874 (values inherits
(comparator-list)))))
876 (defmacro dd-has-raw-slot-p
(dd) `(eq (dd-%element-type
,dd
) '*))
878 ;;;; stuff to parse slot descriptions
880 ;;; Decide whether TYPE as stored in a structure can be a raw slot.
881 ;;; Return the index of the matching RAW-SLOT-DATA if it should be, NIL if not.
882 (defun choose-raw-slot-representation (ctype)
883 ;; If TYPE isn't a subtype of NUMBER, it can't go in a raw slot.
884 ;; In the negative case (which is most often), doing 1 SUBTYPEP test
885 ;; beats doing 5 or 6.
886 (when (and (csubtypep ctype
(specifier-type 'number
))
887 ;; FIXNUMs and smaller go in tagged slots, not raw slots
888 (not (csubtypep ctype
(specifier-type 'fixnum
))))
889 (dotimes (i (length *raw-slot-data
*))
890 (let ((data (svref *raw-slot-data
* i
)))
891 (when (csubtypep ctype
(specifier-type (raw-slot-data-raw-type data
)))
894 ;;; Parse a slot description for DEFSTRUCT, add it to the description
895 ;;; and return it. If supplied, INCLUDED-SLOT is used to get the default,
896 ;;; type, and read-only flag for the new slot.
897 (defun parse-1-dsd (proto-classoid defstruct spec
&optional included-slot
898 &aux accessor-name
(always-boundp t
) (safe-p t
)
899 ctype rsd-index index
)
900 #-sb-xc-host
(declare (muffle-conditions style-warning
))
901 (multiple-value-bind (name default default-p type type-p read-only ro-p
)
905 ((member nil
:conc-name
:constructor
:copier
:predicate
:named
)
906 (warn "slot name of ~S indicates probable syntax error in DEFSTRUCT" spec
))
908 (style-warn "slot name of ~S indicates possible syntax error in DEFSTRUCT" spec
)))
912 (name &optional
(default nil default-p
)
913 &key
(type nil type-p
) (read-only nil ro-p
))
915 (when (dd-conc-name defstruct
)
916 ;; the warning here is useful, but in principle we cannot
917 ;; distinguish between legitimate and erroneous use of
918 ;; these names when :CONC-NAME is NIL. In the common
919 ;; case (CONC-NAME non-NIL), there are alternative ways
920 ;; of writing code with the same effect, so a full
921 ;; warning is justified.
923 ((member :conc-name
:constructor
:copier
:predicate
:include
924 :print-function
:print-object
:type
:initial-offset
:pure
)
925 (warn "slot name of ~S indicates probable syntax error in DEFSTRUCT" name
))))
926 (values name default default-p
927 (uncross type
) type-p
929 (t (%program-error
"in DEFSTRUCT, ~S is not a legal slot description."
932 (when (find name
(dd-slots defstruct
) :test
#'string
= :key
#'dsd-name
)
933 (let* ((parent-name (first (dd-include defstruct
)))
934 (parent (and parent-name
(find-defstruct-description parent-name
)))
935 (included?
(and parent
(find name
940 (%program-error
"slot name ~s duplicated via included ~a"
943 (%program-error
"duplicate slot name ~S" name
))))
945 (setf accessor-name
(if (dd-conc-name defstruct
)
946 (symbolicate (dd-conc-name defstruct
) name
)
948 (let ((predicate-name (dd-predicate-name defstruct
)))
949 (when (eql accessor-name predicate-name
)
950 ;; Some adventurous soul has named a slot so that its accessor
951 ;; collides with the structure type predicate. ANSI doesn't
952 ;; specify what to do in this case. As of 2001-09-04, Martin
953 ;; Atzmueller reports that CLISP and Lispworks both give
954 ;; priority to the slot accessor, so that the predicate is
955 ;; overwritten. We might as well do the same (as well as
956 ;; signalling a warning).
958 "~@<The structure accessor name ~S is the same as the name of the ~
959 structure type predicate. ANSI doesn't specify what to do in ~
960 this case. We'll overwrite the type predicate with the slot ~
961 accessor, but you can't rely on this behavior, so it'd be wise to ~
962 remove the ambiguity in your code.~@:>"
964 (setf (dd-predicate-name defstruct
) nil
))
965 ;; FIXME: It would be good to check for name collisions here, but
968 ;;x(when (and (fboundp accessor-name)
969 ;;x (not (accessor-inherited-data accessor-name defstruct)))
970 ;;x (style-warn "redefining ~/sb-ext:print-symbol-with-prefix/ ~
971 ;; in DEFSTRUCT" accessor-name))
972 ;; which was done until sbcl-0.8.11.18 or so, is wrong: it causes
973 ;; a warning at MACROEXPAND time, when instead the warning should
974 ;; occur not just because the code was constructed, but because it
975 ;; is actually compiled or loaded.
978 (when (and (not default-p
) included-slot
)
979 (setf default
(dsd-default included-slot
)))
981 (let ((inherited-type (if included-slot
(dsd-type included-slot
) t
)))
982 (setf type
(cond ((not type-p
) inherited-type
)
983 ((eq inherited-type t
) type
)
984 (t `(and ,inherited-type
,type
)))))
987 ;; Test whether the type can hold NIL. This avoids a bootstrapping
988 ;; problem involving forward references to undefined types,
989 ;; because we want never to pass unknown types into CROSS-TYPEP.
990 ;; But also, don't call SB-XC:TYPEP on a type-specifier because it does
991 ;; not receive a type-context which specifies the proto-classoid.
992 (when (and (typep type
'(cons (eql or
))) (member 'null type
))
993 (setq ctype
*universal-type
*)) ; a harmless lie
996 (let ((context (make-type-context type proto-classoid
997 +type-parse-cache-inhibit
+)))
998 (setq ctype
(specifier-type type context
)))) ; Parse once only
1000 (cond (included-slot
1002 (setq read-only
(dsd-read-only included-slot
)))
1003 ((and ro-p
(not read-only
) (dsd-read-only included-slot
))
1004 (error "~@<The slot ~S is :READ-ONLY in superclass, and so must ~
1005 be :READ-ONLY in subclass.~:@>"
1007 (setf rsd-index
(dsd-rsd-index included-slot
)
1008 safe-p
(dsd-safe-p included-slot
)
1009 always-boundp
(dsd-always-boundp included-slot
)
1010 index
(dsd-index included-slot
))
1012 (not (equal type
(dsd-type included-slot
)))
1013 (not (subtypep (dsd-type included-slot
) type
)))
1016 ;; Compute the index of this DSD. First decide whether the slot is raw.
1017 (setf rsd-index
(and (eq (dd-type defstruct
) 'structure
)
1018 (choose-raw-slot-representation ctype
)))
1021 (let ((rsd (svref *raw-slot-data
* rsd-index
)))
1022 ;; If slot requires alignment of 2, then ensure that
1023 ;; it has an odd (i.e. doubleword aligned) index.
1024 (when (and (eql (raw-slot-data-alignment rsd
) 2)
1025 (evenp (dd-length defstruct
)))
1026 (incf (dd-length defstruct
)))
1027 (raw-slot-data-n-words rsd
))
1029 (setf index
(dd-length defstruct
))
1030 (incf (dd-length defstruct
) n-words
))))
1031 (when (eq ctype
*empty-type
*)
1032 (with-current-source-form (spec)
1033 (style-warn "The type of the slot ~s is the empty type NIL" name
)))
1034 ;; Check for existence of any BOA constructor that leaves the
1035 ;; slot with an unspecified value, as when it's initialized
1036 ;; by an &AUX binding with no value (CLHS 3.4.6)
1037 (when (and always-boundp
1038 (some (lambda (ctor &aux
(ll-parts (cdr ctor
)))
1039 ;; Keyword constructors store :DEFAULT in the cdr of the cell.
1040 ;; BOA constructors store the parsed lambda list.
1041 (and (listp ll-parts
) ; = (llks req opt rest key aux)
1042 (some (lambda (binding)
1043 (and (or (atom binding
) (not (cdr binding
)))
1044 (string= (if (atom binding
) binding
(car binding
))
1047 (dd-constructors defstruct
)))
1048 (setf always-boundp nil
))
1049 (unless always-boundp
1050 ;; FIXME: the :TYPE option should not preclude storing #<unbound>
1051 ;; unless the storage is a specialized numeric vector.
1052 (when (or rsd-index
(neq (dd-type defstruct
) 'structure
))
1053 (setf always-boundp t safe-p nil
))) ; "demote" to unsafe.
1055 ;; Check for writable slots in pure structures
1057 (when (dd-pure defstruct
)
1059 (format t
"~&structure ~s slot ~s is writable" defstruct name
)))
1061 (let* ((gc-ignorable
1063 (specifier-type '(or fixnum boolean character
1064 #+64-bit single-float
))))
1065 (dsd (make-dsd name type accessor-name
1066 (pack-dsd-bits index read-only safe-p
1067 always-boundp gc-ignorable
1070 (push (cons dsd spec
) *dsd-source-form
*)
1071 (setf (dd-slots defstruct
) (nconc (dd-slots defstruct
) (list dsd
)))
1073 ;; this is enough specialization for now
1074 (cond ((csubtypep ctype
(specifier-type 'character
)) 'char-equal
)
1075 ((csubtypep ctype
(specifier-type 'number
)) '=)
1076 ((csubtypep ctype
(specifier-type 'bit-vector
)) 'bit-vector-
=)
1078 (values dsd comparator
)))))
1080 (defun typed-structure-info-or-lose (name)
1081 (or (info :typed-structure
:info name
)
1082 (error ":TYPE'd DEFSTRUCT ~S not found for inclusion." name
)))
1084 (defmacro dd-element-type
(dd)
1085 `(case (dd-type ,dd
)
1087 ;; %ELEMENT-TYPE might actually be * which is weird
1088 ;; but seems to mostly work. I suspect that it should not.
1089 (dd-%element-type
,dd
))
1091 ;; In theory we have the ability to represent that all slots
1092 ;; of a classoid structure are of type SB-VM:WORD (for example),
1093 ;; but in practice that is not useful.
1094 ;; Just don't return * which is not a type specifier.
1097 ;;; Process any included slots pretty much like they were specified.
1098 ;;; Also inherit various other attributes.
1099 (defun frob-dd-inclusion-stuff (proto-classoid dd option-bits
)
1100 (destructuring-bind (included-name &rest modified-slots
) (dd-include dd
)
1101 (let* ((type (dd-type dd
))
1104 (layout-info (compiler-layout-or-lose included-name
))
1105 (typed-structure-info-or-lose included-name
))))
1107 ;; checks on legality
1108 (unless (and (eq type
(dd-type included-structure
))
1109 (type= (specifier-type (dd-element-type included-structure
))
1110 (specifier-type (dd-element-type dd
))))
1111 (error ":TYPE option mismatch between structures ~S and ~S"
1112 (dd-name dd
) included-name
))
1113 (let ((included-classoid (find-classoid included-name nil
)))
1114 (when included-classoid
1115 ;; It's not particularly well-defined to :INCLUDE any of the
1116 ;; CMU CL INSTANCE weirdosities like CONDITION or
1117 ;; GENERIC-FUNCTION, and it's certainly not ANSI-compliant.
1118 (let* ((included-layout (classoid-layout included-classoid
))
1119 (included-dd (layout-dd included-layout
)))
1120 (when (dd-alternate-metaclass included-dd
)
1121 (error "can't :INCLUDE class ~S (has alternate metaclass)"
1124 ;; A few more sanity checks: every allegedly modified slot exists
1125 ;; and no name appears more than once.
1126 (flet ((included-slot-name (slot-desc)
1127 (if (atom slot-desc
) slot-desc
(car slot-desc
))))
1128 (mapl (lambda (slots &aux
(name (included-slot-name (car slots
))))
1129 (unless (find name
(dd-slots included-structure
)
1130 :test
#'string
= :key
#'dsd-name
)
1131 (%program-error
"slot name ~S not present in included structure"
1133 (when (find name
(cdr slots
)
1134 :test
#'string
= :key
#'included-slot-name
)
1135 (%program-error
"included slot name ~S specified more than once"
1139 (incf (dd-length dd
) (dd-length included-structure
))
1140 (when (dd-class-p dd
)
1141 ;; FIXME: This POSITION call should be foldable without read-time eval
1142 ;; since literals are immutable, and +DD-OPTION-NAMES+ was initialized
1144 (when (and (dd-pure included-structure
)
1145 (not (logbitp #.
(position :pure
+dd-option-names
+) option-bits
)))
1146 (setf (dd-flags dd
) (logior (dd-flags dd
) +dd-pure
+))))
1148 (setf (dd-inherited-accessor-alist dd
)
1149 (dd-inherited-accessor-alist included-structure
))
1150 (collect ((comparator-list))
1151 (dolist (included-slot (dd-slots included-structure
)
1153 (let* ((included-name (dsd-name included-slot
))
1154 (modified (or (find included-name modified-slots
1155 :key
(lambda (x) (if (atom x
) x
(car x
)))
1157 `(,included-name
))))
1158 ;; We stash away an alist of accessors to parents' slots
1159 ;; that have already been created to avoid conflicts later
1160 ;; so that structures with :INCLUDE and :CONC-NAME (and
1161 ;; other edge cases) can work as specified.
1162 (when (dsd-accessor-name included-slot
)
1163 ;; the "oldest" (i.e. highest up the tree of inheritance)
1164 ;; will prevail, so don't push new ones on if they
1166 (pushnew (cons (dsd-accessor-name included-slot
)
1167 (dsd-index included-slot
))
1168 (dd-inherited-accessor-alist dd
)
1169 :test
#'eq
:key
#'car
))
1170 (multiple-value-bind (new-slot comparator
)
1171 (parse-1-dsd proto-classoid dd modified included-slot
)
1172 (comparator-list comparator
)
1173 (when (and (dsd-safe-p included-slot
) (not (dsd-safe-p new-slot
)))
1177 ;;;; various helper functions for setting up DEFSTRUCTs
1179 ;;; This function is called at macroexpand time to compute the INHERITS
1180 ;;; vector for a structure type definition.
1181 ;;; The cross-compiler is allowed to magically compute LAYOUT-INHERITS.
1182 (defun !inherits-for-structure
(info)
1183 (declare (type defstruct-description info
))
1184 (let* ((include (dd-include info
))
1185 (superclass-opt (dd-alternate-metaclass info
))
1188 (compiler-layout-or-lose (first include
))
1189 (classoid-layout (find-classoid
1190 (or (first superclass-opt
)
1191 'structure-object
))))))
1192 (case (dd-name info
)
1194 ;; STREAM is an abstract class and you can't :include it,
1195 ;; so the inheritance has to be hardcoded.
1196 (concatenate 'simple-vector
1197 (layout-inherits super
)
1198 (vector super
(classoid-layout (find-classoid 'stream
)))))
1199 ((fd-stream) ; Similarly, FILE-STREAM is abstract
1200 (concatenate 'simple-vector
1201 (layout-inherits super
)
1203 (classoid-layout (find-classoid 'file-stream
)))))
1204 ((sb-impl::string-input-stream
; etc
1205 sb-impl
::string-output-stream
1206 sb-impl
::fill-pointer-output-stream
)
1207 (concatenate 'simple-vector
1208 (layout-inherits super
)
1210 (classoid-layout (find-classoid 'string-stream
)))))
1211 (pathname (vector (find-layout 't
)))
1212 (logical-pathname (vector (find-layout 't
) (find-layout 'pathname
)))
1213 (t (concatenate 'simple-vector
1214 (layout-inherits super
)
1217 ;;; Do miscellaneous (LOAD EVAL) time actions for the structure
1218 ;;; described by DD. Create the class and LAYOUT, checking for
1219 ;;; incompatible redefinition.
1220 (defun %defstruct
(dd inherits source-location
)
1221 (declare (type defstruct-description dd
))
1223 ;; We set up LAYOUTs even in the cross-compilation host.
1224 (multiple-value-bind (classoid layout old-layout
)
1225 (ensure-structure-class dd inherits
"current" "new")
1226 (cond ((not old-layout
)
1227 (unless (eq (classoid-layout classoid
) layout
)
1228 (register-layout layout
)))
1230 (%redefine-defstruct classoid old-layout layout
)
1231 (let ((old-dd (layout-info old-layout
)))
1232 (when (defstruct-description-p old-dd
)
1233 (dolist (slot (dd-slots old-dd
))
1234 (fmakunbound (dsd-accessor-name slot
))
1235 (unless (dsd-read-only slot
)
1236 (fmakunbound `(setf ,(dsd-accessor-name slot
)))))))
1237 (setq layout
(classoid-layout classoid
))))
1238 ;; Don't want to (setf find-classoid) on a a built-in-classoid
1239 (unless (and (built-in-classoid-p classoid
)
1240 (eq (find-classoid (dd-name dd
) nil
) classoid
))
1241 (setf (find-classoid (dd-name dd
)) classoid
))
1243 (when source-location
1244 (setf (classoid-source-location classoid
) source-location
))))
1247 ;;; Return the transform of OPERATION which is either :READ or :SETF.
1248 ;;; as applied to ARGS, given SLOT-KEY which is a cons of a DD and a DSD.
1249 ;;; FUN-OR-MACRO, which is used only for the :SETF operation,
1250 ;;; indicates whether the argument order corresponds to
1251 ;;; (funcall #'(setf mystruct-myslot) newval s) ; :FUNCTION
1253 ;;; (setf (mystruct-myslot s) newval) ; :MACRO
1254 ;;; Return NIL on failure.
1255 (defun slot-access-transform (operation args slot-key
1257 (fun-or-macro :macro
)
1258 (external-unbound-handling nil
))
1259 (binding* ((dd (car slot-key
))
1260 (dsd (cdr slot-key
))
1261 ((reader writer
) (dsd-reader dsd
(neq (dd-type dd
) 'structure
)))
1262 (type-spec (dsd-type dsd
))
1263 (index (dsd-index dsd
)))
1266 (when (singleton-p args
)
1267 (let* ((instance-form `(the ,(dd-name dd
) ,(car args
)))
1268 (place `(,reader
,instance-form
,index
)))
1269 ;; There are 4 cases of {safe,unsafe} x {always-boundp,possibly-unbound}
1270 ;; If unsafe - which implies TYPE-SPEC other than type T - then we must
1271 ;; check the type on each read. Assuming that type-checks reject
1272 ;; the unbound-marker, then we needn't separately check for it, but if
1273 ;; we're generating code fragments for CLOS (which does its own
1274 ;; EXTERNAL-UNBOUND-HANDLING) we need to let it through explicitly.
1275 (cond ((not (dsd-safe-p dsd
))
1276 (when (and (not (dsd-always-boundp dsd
)) external-unbound-handling
)
1277 (setq type-spec
`(or ,type-spec
(satisfies sb-vm
::unbound-marker-p
))))
1278 `(the ,type-spec
,place
))
1280 ;; unless the slot is always bound, or unbound handling is external,
1281 ;; check here for unbound marker.
1282 (unless (or (dsd-always-boundp dsd
) external-unbound-handling
)
1284 `(the* ((not (satisfies sb-vm
::unbound-marker-p
))
1285 :context
(struct-read-context ,(dd-name dd
) .
,(dsd-name dsd
)))
1288 ((eq type-spec t
) place
)
1290 (when (and (not (dsd-always-boundp dsd
)) external-unbound-handling
)
1291 (setq type-spec
`(or ,type-spec
(satisfies sb-vm
::unbound-marker-p
))))
1292 `(the* (,type-spec
:derive-type-only t
) ,place
))))))))
1294 ;; The primitive object slot setting vops take newval last, which matches
1295 ;; the order in which a use of SETF has them, but because the vops
1296 ;; do not return anything, we have to bind both arguments.
1297 (when (and (listp args
) (singleton-p (cdr args
)))
1298 (multiple-value-bind (newval-form instance-form
)
1300 (:function
(values (first args
) (second args
)))
1301 (:macro
(values (second args
) (first args
))))
1302 (if (eq fun-or-macro
:function
)
1303 ;; This used only for source-transforming (funcall #'(setf myslot) ...).
1304 ;; (SETF x) writer functions have been defined as source-transforms instead of
1305 ;; inline functions, which improved the semantics around clobbering defstruct
1306 ;; writers with random DEFUNs either deliberately or accidentally.
1307 ;; Since users can't define source-transforms (not portably anyway),
1308 ;; we can easily discern which functions were system-generated.
1311 ((eq type-spec t
) newval-form
)
1313 (unless (or (dsd-always-boundp dsd
) (not external-unbound-handling
))
1314 (setq type-spec
`(or ,type-spec
(satisfies sb-vm
::unbound-marker-p
))))
1315 `(the* (,type-spec
:context
(struct-context ,(dd-name dd
) .
,(dsd-name dsd
)))
1317 (#1=#:instance
#3=(the ,(dd-name dd
) ,instance-form
)))
1318 (,writer
#1# ,index
#2#)
1320 `(let ((#1# #3#) (#2# #4#)) (,writer
#1# ,index
#2#) #2#))))))))
1322 ;;; Apply TRANSFORM - a special indicator stored in :SOURCE-TRANSFORM
1323 ;;; for a DEFSTRUCT copier, accessor, or predicate - to SEXPR.
1324 ;;; NAME is needed to select between the reader and writer transform.
1325 (defun sb-c::struct-fun-transform
(transform sexpr name
)
1326 (let* ((snippet (cdr transform
))
1328 (cond ((eq snippet
:constructor
)
1329 ;; All defstruct-defined things use the :source-transform as
1330 ;; an indicator of magic-ness, but actually doing the transform
1331 ;; for constructors could cause inadvertent variable capture.
1333 ((symbolp snippet
) ; predicate or copier
1334 (when (singleton-p (cdr sexpr
)) ; exactly 1 arg
1335 (let ((type (dd-name (car transform
)))
1338 (:predicate
`(sb-c::%instance-typep
,arg
',type
))
1339 (:copier
`(copy-structure (the ,type
,arg
)))))))
1341 (slot-access-transform (if (consp name
) :setf
:read
)
1342 (cdr sexpr
) transform
:function
)))))
1343 (values result
(not result
))))
1345 ;;; Blow away all the compiler info for the structure CLASS. Iterate
1346 ;;; over this type, clearing the compiler structure type info, and
1347 ;;; undefining all the associated functions. If SUBCLASSES-P, also do
1348 ;;; the same for subclasses. FIXME: maybe rename UNDEFINE-FUN-NAME to
1349 ;;; UNDECLARE-FUNCTION-NAME?
1350 (defun undeclare-structure (classoid subclasses-p
)
1351 (let ((info (layout-%info
(classoid-layout classoid
))))
1352 (when (defstruct-description-p info
)
1353 (let ((type (dd-name info
)))
1354 (clear-info :type
:compiler-layout type
)
1355 ;; FIXME: shouldn't this undeclare any constructors too?
1356 (undefine-fun-name (dd-copier-name info
))
1357 (undefine-fun-name (dd-predicate-name info
))
1358 (dolist (slot (dd-slots info
))
1359 (let ((fun (dsd-accessor-name slot
)))
1360 (unless (accessor-inherited-data fun info
)
1361 (undefine-fun-name fun
)
1362 (unless (dsd-read-only slot
)
1363 (undefine-fun-name `(setf ,fun
)))))))
1364 ;; Clear out the SPECIFIER-TYPE cache so that subsequent
1365 ;; references are unknown types.
1366 (values-specifier-type-cache-clear)))
1369 (do-subclassoids ((classoid layout
) classoid
)
1370 (declare (ignore layout
))
1371 (undeclare-structure classoid nil
)
1372 (subs (classoid-proper-name classoid
)))
1373 ;; Is it really necessary to warn about
1374 ;; undeclaring functions for subclasses?
1376 (warn "undeclaring functions for old subclasses of ~S:~% ~S"
1377 (classoid-name classoid
) (subs))))))
1379 ;;; core compile-time setup of any class with a LAYOUT, used even by
1380 ;;; !DEFSTRUCT-WITH-ALTERNATE-METACLASS weirdosities
1381 (defun %compiler-set-up-layout
(dd inherits
)
1382 (multiple-value-bind (classoid layout old-layout
)
1383 (multiple-value-bind (clayout clayout-p
)
1384 (info :type
:compiler-layout
(dd-name dd
))
1385 (ensure-structure-class dd
1388 "The most recently compiled"
1390 "the most recently loaded"
1391 :compiler-layout clayout
))
1393 (undeclare-structure (layout-classoid old-layout
)
1394 (and (classoid-subclasses classoid
)
1395 (not (eq layout old-layout
))))
1396 (setf (layout-invalid layout
) nil
)
1397 ;; FIXME: it might be polite to hold onto old-layout and
1398 ;; restore it at the end of the file. -- RMK 2008-09-19
1399 ;; (International Talk Like a Pirate Day).
1400 (warn "~@<Clobbering the compiler's idea of the layout of ~A.~:@>"
1403 (unless (eq (classoid-layout classoid
) layout
)
1404 (register-layout layout
:invalidate nil
))
1405 ;; Don't want to (setf find-classoid) on a a built-in-classoid
1406 (unless (and (built-in-classoid-p classoid
)
1407 (eq (find-classoid (dd-name dd
) nil
) classoid
))
1408 (setf (find-classoid (dd-name dd
)) classoid
))))
1410 ;; At this point the class should be set up in the INFO database.
1411 ;; But the logic that enforces this is a little tangled and
1412 ;; scattered, so it's not obvious, so let's check.
1413 (aver (find-classoid (dd-name dd
) nil
))
1415 (setf (info :type
:compiler-layout
(dd-name dd
)) layout
))
1418 (defun %proclaim-defstruct-ctors
(dd)
1419 (aver (not (dd-class-p dd
)))
1420 (let ((info `(,dd .
:constructor
)))
1421 (dolist (ctor (dd-constructors dd
))
1422 (setf (info :function
:source-transform
(car ctor
)) info
))))
1424 ;;; Do (COMPILE LOAD EVAL)-time actions for the structure described by DD
1425 ;;; which may be a "normal" defstruct or an alternate-metaclass struct.
1426 ;;; This includes generation of a style-warning about previously compiled
1427 ;;; calls to the accessors and/or predicate that weren't inlined.
1428 (defun %compiler-defstruct
(dd inherits
)
1429 (declare (type defstruct-description dd
))
1431 (aver (dd-class-p dd
)) ; LIST and VECTOR representation are not allowed
1432 (let ((check-inlining
1433 ;; Why use the secondary result of INFO, not the primary?
1434 ;; Because when DEFSTRUCT is evaluated, not via the file-compiler,
1435 ;; the first thing to happen is %DEFSTRUCT, which sets up FIND-CLASS.
1436 ;; Due to :COMPILER-LAYOUT's defaulting expression in globaldb,
1437 ;; it has a value - the layout of the classoid - that we don't want.
1438 ;; Also, since structures are technically not redefineable,
1439 ;; I don't worry about failure to inline a function that was
1440 ;; formerly not known as an accessor but now is.
1441 (null (nth-value 1 (info :type
:compiler-layout
(dd-name dd
)))))
1443 (%compiler-set-up-layout dd inherits
)
1444 (let ((xform `(,dd .
:constructor
)))
1445 (dolist (ctor (dd-constructors dd
))
1446 ;; Don't check-inlining because ctors aren't always inlined
1447 (setf (info :function
:source-transform
(car ctor
)) xform
)))
1448 (awhen (dd-copier-name dd
)
1449 (when check-inlining
(push it fnames
))
1450 (setf (info :function
:source-transform it
) (cons dd
:copier
)))
1451 (awhen (dd-predicate-name dd
)
1452 (when check-inlining
(push it fnames
))
1453 (setf (info :function
:source-transform it
) (cons dd
:predicate
)))
1455 (dolist (dsd (dd-slots dd
))
1456 (let ((accessor-name (dsd-accessor-name dsd
)))
1457 ;; Why this WHEN guard here, if there is neither a standards-specified
1458 ;; nor implementation-specific way to skip defining an accessor? Dunno.
1459 ;; And furthermore, by ignoring a package lock, it's possible to name
1460 ;; an accessor NIL: (defstruct (x (:conc-name "N")) IL)
1461 ;; making this test kinda bogus in two different ways.
1463 (let ((inherited (accessor-inherited-data accessor-name dd
)))
1466 (let ((writer `(setf ,accessor-name
))
1467 (slot-key (cons dd dsd
)))
1468 (when check-inlining
1469 (push accessor-name fnames
))
1470 (setf (info :function
:source-transform accessor-name
)
1472 (unless (dsd-read-only dsd
)
1473 (when check-inlining
1474 (push writer fnames
))
1475 (setf (info :function
:source-transform writer
) slot-key
))))
1476 ((not (= (cdr inherited
) (dsd-index dsd
)))
1477 (style-warn "~@<Non-overwritten accessor ~S does not access ~
1478 slot with name ~S (accessing an inherited slot ~
1481 (dsd-name dsd
))))))))
1483 (awhen (remove-if-not #'sb-c
::emitted-full-call-count fnames
)
1484 (sb-c:compiler-style-warn
1485 'sb-c
:inlining-dependency-failure
1486 ;; This message omits the http://en.wikipedia.org/wiki/Serial_comma
1487 :format-control
"~@<Previously compiled call~P to ~
1488 ~{~/sb-ext:print-symbol-with-prefix/~^~#[~; and~:;,~] ~} ~
1489 could not be inlined because the structure definition for ~
1490 ~/sb-ext:print-symbol-with-prefix/ was not yet seen. To avoid this warning, ~
1491 DEFSTRUCT should precede references to the affected functions, ~
1492 or they must be declared locally notinline at each call site.~@:>"
1493 :format-arguments
(list (length it
) (nreverse it
) (dd-name dd
))))))
1495 ;;;; redefinition stuff
1497 ;;; Compare the slots of OLD and NEW, returning 3 lists of slot names:
1498 ;;; 1. Slots which have moved,
1499 ;;; 2. Slots whose type has changed,
1500 ;;; 3. Deleted slots.
1501 (defun compare-slots (old new
)
1502 (let* ((oslots (dd-slots old
))
1503 (nslots (dd-slots new
))
1504 (onames (mapcar #'dsd-name oslots
))
1505 (nnames (mapcar #'dsd-name nslots
)))
1508 (dolist (name (intersection onames nnames
))
1509 (let ((os (find name oslots
:key
#'dsd-name
:test
#'string
=))
1510 (ns (find name nslots
:key
#'dsd-name
:test
#'string
=)))
1511 (unless (subtypep (dsd-type ns
) (dsd-type os
))
1513 (unless (and (= (dsd-index os
) (dsd-index ns
))
1514 (eq (dsd-raw-type os
) (dsd-raw-type ns
)))
1518 (set-difference onames nnames
:test
#'string
=)))))
1520 ;;; If we are redefining a structure with different slots than in the
1521 ;;; currently loaded version, give a warning and return true.
1522 (defun redefine-structure-warning (classoid old new
)
1523 (declare (type defstruct-description old new
)
1524 (type classoid classoid
)
1526 (let ((name (dd-name new
)))
1527 (multiple-value-bind (moved retyped deleted
) (compare-slots old new
)
1528 (when (or moved retyped deleted
)
1530 "incompatibly redefining slots of structure class ~S~@
1531 Make sure any uses of affected accessors are recompiled:~@
1532 ~@[ These slots were moved to new positions:~% ~S~%~]~
1533 ~@[ These slots have new incompatible types:~% ~S~%~]~
1534 ~@[ These slots were deleted:~% ~S~%~]"
1535 name moved retyped deleted
)
1538 ;;; Return true if destructively modifying OLD-LAYOUT into NEW-LAYOUT
1539 ;;; would be possible in as much as it won't harm the garbage collector.
1540 ;;; Harm potentially results from turning a raw word into a tagged word.
1541 ;;; There are additional mutations which would be permissible but don't
1542 ;;; strike me as important - e.g. permitting a fixnum slot to become type T
1543 ;;; is permissible, but the fixnum may or may not be marked as tagged
1544 ;;; in the bitmap, depending on whether any raw slot exists.
1545 ;;; I can't imagine that many users will complain that they can no longer
1546 ;;; incompatibly redefine defstructs involving raw slots.
1547 ;;; Additionally, it is no longer possible to RECKLESSLY-CONTINUE on a defstruct
1548 ;;; if the number of words in the layout would differ due to extra ID words,
1549 ;;; but given that it was already not possible if the bitmaps differ,
1550 ;;; it does not seem a big sacrifice to disallow redefining structures
1551 ;;; at depthoids in excess of 7 (LAYOUT-ID-VECTOR-FIXED-CAPACITY) unless
1552 ;;; both the old and new structure are at the same depthoid.
1554 (defun mutable-layout-p (old-layout new-layout
)
1555 (declare (type layout old-layout new-layout
))
1556 (if (layout-info old-layout
)
1557 (let ((old-bitmap (%layout-bitmap old-layout
))
1558 (new-bitmap (%layout-bitmap new-layout
)))
1559 ;; The number of extra ID words has to match, as does the number of bitmap
1560 ;; words, or else GC will croak when parsing the bitmap.
1561 (and (= (calculate-extra-id-words (layout-depthoid old-layout
))
1562 (calculate-extra-id-words (layout-depthoid new-layout
)))
1563 (= (bitmap-nwords new-layout
)
1564 (bitmap-nwords old-layout
))
1565 (dotimes (i (dd-length (layout-dd old-layout
)) t
)
1566 (when (and (logbitp i new-bitmap
) ; a tagged (i.e. scavenged) slot
1567 (not (logbitp i old-bitmap
))) ; that was opaque bits
1571 ;;; This function is called when we are incompatibly redefining a
1572 ;;; structure CLASS to have the specified NEW-LAYOUT. We signal an
1573 ;;; error with some proceed options and return the layout that should
1575 (defun %redefine-defstruct
(classoid old-layout new-layout
)
1576 (declare (type classoid classoid
)
1577 (type layout old-layout new-layout
))
1578 (declare (ignorable old-layout
)) ; for host
1579 (let ((name (classoid-proper-name classoid
)))
1581 (error "~@<attempt to redefine the ~S class ~S incompatibly with the current definition~:@>"
1587 "~@<Use the new definition of ~S, invalidating ~
1588 already-loaded code and instances.~@:>"
1590 (register-layout new-layout
))
1592 (recklessly-continue ()
1594 (declare (ignore c
))
1595 (mutable-layout-p old-layout new-layout
))
1598 "~@<Use the new definition of ~S as if it were ~
1599 compatible, allowing old accessors to use new ~
1600 instances and allowing new accessors to use old ~
1603 ;; classic CMU CL warning: "Any old ~S instances will be in a bad way.
1604 ;; I hope you know what you're doing..."
1605 (register-layout new-layout
1607 :destruct-layout old-layout
))))
1610 (defun dd-custom-gc-method-p (dd)
1611 (cond ((eq (dd-name dd
) 'sb-lockless
::list-node
) t
)
1613 (dd-custom-gc-method-p
1614 (layout-info (compiler-layout-or-lose (car (dd-include dd
))))))))
1616 ;;; Compute DD's bitmap, storing 1 for each tagged word.
1617 ;;; The GC can parse signed fixnums and bignums, with which we can
1618 ;;; represent an unlimited number of "&rest" slots all with the same
1619 ;;; nature - tagged or raw. If REST is :TAGGED or :UNTAGGED, it
1620 ;;; specifies a particular nature. If :UNSPECIFIC, then we sign-extend
1621 ;;; from the last specified slot which tends to reduce the bitmap to
1622 ;;; -1 in the case of everything being tagged, (or -2 if non-compact
1623 ;;; header), or a small positive fixnum if the last is untagged.
1625 ;;; Bit indices correspond to physical word indices excluding
1626 ;;; the header word. So the least-significant bit of a bitmap is
1627 ;;; always the word just after the instance header word.
1629 ;;; Examples: (Legend: u=untaggged slot, t=tagged slot)
1631 ;;; logical arithmetic
1633 ;;; Funcallable object:
1634 ;;; Executable w/ standard header: #b.101000 -24
1636 ;;; word1: (*) entry address
1637 ;;; word2: (u) machine instructions
1638 ;;; word3: (u) machine instructions
1639 ;;; word4: (t) implementation-fun
1640 ;;; word5: (u) layout
1641 ;;; word6: (t) tagged slots ...
1642 ;;; Executable w/ compact header: #b...1000 -8
1643 ;;; word0: header/layout
1644 ;;; word1: (*) entry address
1645 ;;; word2: (u) machine instructions
1646 ;;; word3: (u) machine instructions
1647 ;;; word4: (t) implementation-fun
1648 ;;; word5: (t) tagged slots ...
1649 ;;; Non-executable: #b...1010 -6
1651 ;;; word1: (*) entry address
1652 ;;; word2: (t) implementation-fun
1653 ;;; word3: (u) layout
1654 ;;; word4: (t) tagged slots ...
1655 ;;; (*) entry address can be treated as either tagged or raw.
1656 ;;; For some architectures it has a lowtag, but points to
1657 ;;; read-only space. For others it is a fixnum.
1658 ;;; In either case the GC need not observe the value.
1659 (defconstant funinstance-layout-bitmap
1660 #-executable-funinstances -
6
1661 #+(and executable-funinstances
(not compact-instance-header
)) -
24
1662 #+(and executable-funinstances compact-instance-header
) -
8)
1665 ;;; Ordinary instance with only tagged slots:
1666 ;;; Non-compact header: #b...1110 -2
1668 ;;; word1: (u) layout
1669 ;;; word2: (t) tagged slots ...
1670 ;;; Compact header: #b...1111 -1
1671 ;;; word0: header/layout
1672 ;;; word1: (t) tagged slots ...
1673 ;;; Ordinary instance with only raw slots slots:
1674 ;;; [this also includes objects whose slots all have types
1675 ;;; ignorable by GC such as fixum/character]
1676 ;;; Non-compact header: #b...0000 0
1678 ;;; word1: (u) layout
1679 ;;; word2: (u) raw slots ...
1680 ;;; Compact header: #b...0000 0
1681 ;;; word0: header/layout
1682 ;;; word1: (u) raw slots ...
1685 ;;; 1. LAYOUT has to be scanned separately regardless of where stored.
1686 ;;; (compact header or not). Hence it is regarded as an untagged slot.
1687 ;;; 2. For funcallable objects these examples are exhaustive of all
1688 ;;; possible bitmaps. The instance length can be anything,
1689 ;;; but untagged slots are not generally supported.
1690 ;;; For ordinary instance the examples are merely illustrative.
1692 (defun calculate-dd-bitmap (dd &optional
(rest :unspecific
))
1693 (declare (type (member :unspecific
:tagged
:untagged
) rest
))
1695 (when (eq (dd-name dd
) 'layout
)
1696 (setf rest
:untagged
))
1697 (when (eq (car (dd-alternate-metaclass dd
)) 'function
)
1698 (return-from calculate-dd-bitmap funinstance-layout-bitmap
))
1699 ;; Compute two masks with a 1 bit for each dsd-index which contains a descriptor.
1700 ;; The "mininal" bitmap contains a 1 for each slot which *must* be scanned in GC,
1701 ;; and the "maximal" bitmap contains a 1 for each which *may* be scanned.
1702 ;; If a non-raw slot type can be ignored - such as (OR FIXNUM NULL), then it
1703 ;; sets a 1 in the maximal bitmap but not in the minimal bitmap.
1704 ;; Note that the GC can always add one slot for a stable hash, but that slot
1705 ;; can only hold a fixnum, so need not be traced even though it is a descriptor.
1706 (let ((n-bits (dd-length dd
))
1710 (dolist (slot (dd-slots dd
))
1711 (cond ((eql t
(dsd-raw-type slot
))
1712 (let ((bit (ash 1 (dsd-index slot
))))
1713 (setf maximal-bitmap
(logior maximal-bitmap bit
))
1714 (unless (dsd-gc-ignorable slot
)
1715 (setf minimal-bitmap
(logior minimal-bitmap bit
)))))
1719 ;; If the structure has a custom GC scavenging method then always return
1720 ;; the minimal bitmap, and disallow arbitrary trailing slots.
1721 ;; The optimization for all-tagged (avoiding use of the bitmap)
1722 ;; indicates in addition to no raw slots, no custom GC method either.
1723 ;; As of now this only pertains to lockfree-singly-linked-list nodes
1724 ;; and descendant types. (The lockfree list uses one pointer bit
1725 ;; as a pending-deletion flag. See "src/code/target-lflist.lisp")
1726 (when (dd-custom-gc-method-p dd
)
1727 (aver (eq rest
:unspecific
))
1728 ;; Pretend there are raw slots so that the layout
1729 ;; does not get the STRICTLY-BOXED flag set.
1730 (return-from calculate-dd-bitmap
(values minimal-bitmap t
)))
1732 ;; The minimal bitmap will have the least number of bits set, and the maximal
1733 ;; will have the most, but it is not always a performance improvement to prefer
1734 ;; fewer bits. If the total number of bits is large, and there are no raw slots,
1735 ;; then the "all tagged" treatment may be better because it does not need to
1736 ;; parse the bitmap. But if there are any raw slots, the minimal bitmap is best.
1738 (if (or (= minimal-bitmap
0) ; don't need a bitmap
1739 any-raw
; must use a bitmap
1740 ;; for other cases, it is not clear-cut
1741 (and (> (logcount maximal-bitmap
) 10) ; arb
1742 (< (logcount minimal-bitmap
)
1743 (floor (logcount maximal-bitmap
) 2))))
1747 ;; If the trailing slots have tagged nature, extend bitmap with
1748 ;; an infinite sequence of 1 bits. If :UNSPECIFIC, replicate
1749 ;; the most-significant-bit whether it be 0 or 1.
1750 (values (cond ((or (eq rest
:tagged
)
1751 (and (eq rest
:unspecific
)
1753 (logbitp (1- n-bits
) bitmap
)))
1754 (dpb bitmap
(byte n-bits
0) -
1))
1759 ;;; This is called when we are about to define a structure class. It
1760 ;;; returns a (possibly new) class object and the layout which should
1761 ;;; be used for the new definition (may be the current layout, and
1762 ;;; also might be an uninstalled forward referenced layout.) The third
1763 ;;; value is true if this is an incompatible redefinition, in which
1764 ;;; case it is the old layout.
1765 (defun ensure-structure-class (info inherits old-context new-context
1766 &key compiler-layout
1768 (declare (type defstruct-description info
))
1769 (multiple-value-bind (classoid old-layout
)
1770 (multiple-value-bind (class constructor
)
1771 (acond ((cdr (dd-alternate-metaclass info
))
1772 (values (first it
) (second it
)))
1774 (values 'structure-classoid
'make-structure-classoid
)))
1775 (insured-find-classoid (dd-name info
)
1777 (structure-classoid #'structure-classoid-p
)
1778 (built-in-classoid #'built-in-classoid-p
)
1779 (static-classoid #'static-classoid-p
)
1780 (condition-classoid #'condition-classoid-p
))
1782 (setf (classoid-direct-superclasses classoid
)
1783 (case (dd-name info
)
1784 ;; Argh, could this case be any more opaque???
1785 ;; It's ostensibly the set of types whose superclasse would come out wrong
1786 ;; if we didn't fudge them manually. But the computation of the superclass
1787 ;; list is obfuscated. I think we have assertions about this somewhere.
1788 ;; But ideally we remove this junky case from the target image somehow
1789 ;; while leaving it in for self-build.
1792 sb-impl
::string-input-stream sb-impl
::string-output-stream
1793 sb-impl
::fill-pointer-output-stream
)
1794 (list (layout-classoid (svref inherits
(1- (length inherits
))))
1795 (layout-classoid (svref inherits
(- (length inherits
) 2)))))
1797 (list (layout-classoid
1798 (svref inherits
(1- (length inherits
))))))))
1799 (unless (dd-alternate-metaclass info
)
1800 (setq flags
+structure-layout-flag
+))
1801 (cond ((some #'dsd-rsd-index
(dd-slots info
))) ; mixed boxed + raw (or wholly raw)
1802 ((and (not (dd-alternate-metaclass info
))
1803 (not (dd-custom-gc-method-p info
)))
1804 (setf flags
(logior flags
+strictly-boxed-flag
+))))
1805 ;; FIXME: explain why this is #-sb-xc-host.
1807 (dovector (ancestor inherits
)
1808 (setq flags
(logior (logand (logior +stream-layout-flag
+
1809 +file-stream-layout-flag
+
1810 +string-stream-layout-flag
+)
1811 (layout-flags ancestor
))
1813 (let* ((old-layout (or compiler-layout old-layout
))
1815 (when (or (not old-layout
) *type-system-initialized
*)
1816 (make-layout (hash-layout-name (dd-name info
))
1820 :depthoid
(length inherits
)
1821 :length
(dd-length info
)
1825 (values classoid new-layout nil
))
1827 ;; The assignment of INFO here can almost be deleted,
1828 ;; except for a few magical types that don't d.t.r.t. in cold-init:
1829 ;; STRUCTURE-OBJECT, CONDITION, ALIEN-VALUE, INTERPRETED-FUNCTION
1830 (setf (layout-info old-layout
) info
)
1831 (values classoid old-layout nil
))
1832 (;; This clause corresponds to an assertion in REDEFINE-LAYOUT-WARNING
1833 ;; of classic CMU CL. I moved it out to here because it was only
1834 ;; exercised in this code path anyway. -- WHN 19990510
1835 (not (eq (layout-classoid new-layout
) (layout-classoid old-layout
)))
1836 (error "shouldn't happen: weird state of OLD-LAYOUT?"))
1837 ((warn-if-altered-layout old-context
1840 (layout-length new-layout
)
1841 (layout-inherits new-layout
)
1842 (layout-depthoid new-layout
)
1843 (layout-bitmap new-layout
))
1844 (values classoid new-layout old-layout
))
1846 (let ((old-info (layout-info old-layout
)))
1848 (cond ((redefine-structure-warning classoid old-info info
)
1849 (values classoid new-layout old-layout
))
1851 (setf (layout-info old-layout
) info
)
1852 (values classoid old-layout nil
)))
1854 (setf (layout-info old-layout
) info
)
1855 (values classoid old-layout nil
)))))))))
1857 ;;; Return a list of pairs (name . index). Used for :TYPE'd
1858 ;;; constructors to find all the names that we have to splice in &
1859 ;;; where. Note that these types don't have a layout, so we can't look
1860 ;;; at LAYOUT-INHERITS.
1861 (defun find-name-indices (defstruct)
1864 (do ((info defstruct
1865 (typed-structure-info-or-lose (first (dd-include info
)))))
1866 ((not (dd-include info
))
1871 (dolist (info infos
)
1872 (incf i
(or (dd-offset info
) 0))
1873 (when (dd-named info
)
1874 (res (cons (dd-name info
) i
)))
1875 (setq i
(dd-length info
)))))
1879 ;;; These functions are called to actually make a constructor after we
1880 ;;; have processed the arglist. The correct variant (according to the
1881 ;;; DD-TYPE) should be called. The function is defined with the
1882 ;;; specified name and arglist. VARS and TYPES are used for argument
1883 ;;; type declarations. VALUES are the values for the slots (in order.)
1885 ;;; This is split into two functions:
1886 ;;; * INSTANCE-CONSTRUCTOR-FORM has to deal with raw slots
1887 ;;; * TYPED-CONSTRUCTOR-FORM deal with LIST & VECTOR
1888 ;;; which might have "name" symbols stuck in at various weird places.
1889 (defun instance-constructor-form (dd values
&aux
(dd-slots (dd-slots dd
)))
1890 (aver (= (length dd-slots
) (length values
)))
1891 (collect ((slot-specs) (slot-values))
1892 (mapc (lambda (dsd value
&aux
(raw-type (dsd-raw-type dsd
))
1893 (spec (list* :slot raw-type
(dsd-index dsd
))))
1894 (cond ((eq value
'.do-not-initialize-slot.
)
1895 (when (eq raw-type t
)
1896 (rplaca spec
:unbound
)
1900 (slot-values value
))))
1902 `(%make-structure-instance-macro
,dd
',(slot-specs) ,@(slot-values)))
1905 ;;; A "typed" constructor prefers to use a single call to LIST or VECTOR
1906 ;;; if possible, but can't always do that for VECTOR because it might not
1907 ;;; be a (VECTOR T). If not, we fallback to MAKE-ARRAY and (SETF AREF).
1908 (defun typed-constructor-form (dd values
)
1909 (multiple-value-bind (operator initial-element
)
1910 (cond ((and (eq (dd-type dd
) 'vector
) (eq (dd-%element-type dd
) t
))
1912 ((eq (dd-type dd
) 'list
)
1913 (values 'list nil
)))
1914 (let* ((length (dd-length dd
))
1915 (slots (dd-slots dd
))
1916 ;; Possibly the most useless feature ever: more than one name slot.
1917 (names (find-name-indices dd
)))
1918 (aver (= (length slots
) (length values
)))
1920 ;; The initial-element provides values for slots that are skipped
1921 ;; due to :initial-offset, not slots that are skipped due to
1922 ;; &AUX variables with no initial value.
1923 (let ((vals (make-list length
:initial-element initial-element
)))
1925 (setf (elt vals
(cdr x
)) `',(car x
)))
1926 (mapc (lambda (dsd val
)
1927 ;; For both vectors and lists, .DO-NOT-INITIALIZE-SLOT.
1928 ;; becomes 0 even though lists otherwise use NIL for slots
1929 ;; that are skipped to due :initial-offset.
1930 (setf (elt vals
(dsd-index dsd
))
1931 ;; All VALs have been wrapped in THE if necessary.
1932 (if (eq val
'.do-not-initialize-slot.
) 0 val
)))
1934 (cons operator vals
))
1935 (let ((temp (make-symbol "OBJ")))
1936 `(let ((,temp
(make-array ,length
1937 :element-type
',(dd-%element-type dd
))))
1938 ,@(mapcar (lambda (x) `(setf (aref ,temp
,(cdr x
)) ',(car x
)))
1940 ,@(mapcan (lambda (dsd val
)
1941 (unless (eq val
'.do-not-initialize-slot.
)
1942 `((setf (aref ,temp
,(dsd-index dsd
)) ,val
))))
1946 ;;; Return the FTYPE for a DD constructor.
1947 ;;; This is tricky in uses such as the following:
1948 ;;; (DEFSTRUCT (S (:CONSTRUCTOR MS (A &AUX (A (ABS A))))) (A 0 :TYPE (MOD 4)))
1949 ;;; The constructor accepts integers betweeen -3 and 3 because the &AUX binding
1950 ;;; hides the positional argument A, and we can't actually put any constraint
1951 ;;; on A unless we figure out what the action of ABS is.
1953 ;;; The FTYPE is actually not a strong enough constraint anyway, so when IR1
1954 ;;; tests for the call compatibility it will test for correctness *after*
1955 ;;; argument defaulting.
1956 (defun %struct-ctor-ftype
(dd args elt-type
)
1957 (flet ((elt-type-intersect (dsd &aux
(slot-type (dsd-type dsd
)))
1958 (cond ((eq slot-type t
) elt-type
)
1959 ((eq elt-type t
) slot-type
)
1960 (t `(and ,elt-type
,slot-type
)))))
1962 ,(if (eq args
:default
)
1963 `(&key
,@(mapcar (lambda (dsd)
1964 `(,(keywordicate (dsd-name dsd
))
1965 ,(elt-type-intersect dsd
)))
1967 (destructuring-bind (llks &optional req opt rest keys aux
) args
1968 (let ((aux (mapcar (lambda (var) (if (listp var
) (car var
) var
))
1970 (flet ((get-arg-type (name)
1971 (let ((slot (unless (member name aux
:test
#'string
=)
1972 (find name
(dd-slots dd
) :key
#'dsd-name
1974 ;; If no slot, the arg restriction is T,
1975 ;; because we don't know where it goes.
1976 (if slot
(elt-type-intersect slot
) t
))))
1978 llks nil
(mapcar #'get-arg-type req
)
1979 (mapcar (lambda (arg)
1980 (get-arg-type (parse-optional-arg-spec arg
)))
1983 (mapcar (lambda (arg)
1984 (multiple-value-bind (key var
) (parse-key-arg-spec arg
)
1985 `(,key
,(get-arg-type var
))))
1987 (values ,(cond ((dd-class-p dd
) (dd-name dd
))
1988 ((eq (dd-type dd
) 'list
) 'list
)
1989 (t `(vector ,(dd-%element-type dd
) ,(dd-length dd
))))
1992 ;;; Return the ftype of global function NAME.
1993 (defun global-ftype (name &aux xform
)
1994 (multiple-value-bind (type foundp
) (info :function
:type name
)
1996 #-sb-xc-host
; PCL "doesn't exist" yet
1997 ((eq type
:generic-function
) (sb-pcl::compute-gf-ftype name
))
1998 ((consp type
) ; not parsed type
1999 ;; This case is used only for DEFKNOWN. It allows some out-of-order
2000 ;; definitions during bootstrap while avoiding the "uncertainty in typep"
2001 ;; error. It would work for user code as well, but users shouldn't write
2002 ;; out-of-order type definitions. In any case, it's not wrong to leave
2004 (let ((ctype (specifier-type type
)))
2005 (unless (contains-unknown-type-p ctype
)
2006 (setf (info :function
:type name
) ctype
))
2008 ;; In the absence of global info for a defstruct snippet, get the compiler's
2009 ;; opinion based on the defstruct definition, rather than reflecting on the
2010 ;; current function (as defined "now") which is what globaldb would get in
2011 ;; effect by calling FTYPE-FROM-FDEFN, that being less precise.
2013 (typep (setq xform
(info :function
:source-transform name
))
2014 '(cons defstruct-description
)))
2015 (let* ((dd (car xform
))
2016 (snippet (cdr xform
))
2017 (dd-name (dd-name dd
)))
2021 (let ((ctor (assq name
(dd-constructors dd
))))
2023 (%struct-ctor-ftype dd
(cdr ctor
) (dd-element-type dd
))))
2024 (:predicate
`(function (t) (values boolean
&optional
)))
2025 (:copier
`(function (,dd-name
) (values ,dd-name
&optional
)))
2027 (let ((type (dsd-type snippet
)))
2029 `(function (,type
,dd-name
) (values ,type
&optional
)) ; writer
2030 `(function (,dd-name
) (values ,type
&optional
))))))))) ; reader
2034 ;;; Given a DD and a constructor spec (a cons of name and pre-parsed
2035 ;;; BOA lambda list, or the symbol :DEFAULT), return the effective
2036 ;;; lambda list and the body of the lambda.
2037 (defun structure-ctor-lambda-parts
2038 (dd args
&aux
(creator (ecase (dd-type dd
)
2039 (structure #'instance-constructor-form
)
2040 ((list vector
) #'typed-constructor-form
))))
2041 (labels ((default-value (dsd &optional pretty
)
2042 (let ((default (dsd-default dsd
))
2043 (type (dsd-type dsd
))
2044 (source-form (and (boundp '*dsd-source-form
*)
2045 (cdr (assq dsd
*dsd-source-form
*)))))
2048 `(the* (,type
:source-form
,source-form
2052 ((and default source-form
2054 `(sb-c::with-source-form
,source-form
2058 (parse (&optional pretty
)
2059 (mapcar (lambda (dsd)
2060 (let* ((temp (copy-symbol (dsd-name dsd
)))
2061 (keyword (keywordicate temp
)))
2063 ,(default-value dsd pretty
))))
2065 (when (eq args
:default
)
2066 (let ((lambda-list (parse)))
2067 (return-from structure-ctor-lambda-parts
2068 `((&key
,@lambda-list
)
2069 (declare (explicit-check)
2070 (sb-c::lambda-list
(&key
,@(parse t
))))
2071 ,(funcall creator dd
2072 (mapcar (lambda (dsd arg
)
2073 (let ((type (dsd-type dsd
))
2077 `(the* (,type
:context
2078 (struct-context ,(dd-name dd
) .
,(dsd-name dsd
)))
2080 (dd-slots dd
) lambda-list
))))))
2081 (destructuring-bind (llks &optional req opt rest keys aux
) args
2082 (collect ((vars (copy-list req
)) ; list of bound vars
2085 (dolist (binding aux
)
2086 (let ((name (if (listp binding
) (car binding
) binding
)))
2088 (unless (typep binding
'(cons t cons
))
2089 (skipped-vars name
))))
2090 (macrolet ((rewrite (input key parse pretty
)
2093 (multiple-value-bind (,@key var def sup-p
) (,parse arg
)
2094 (declare (ignore ,@key def
))
2095 (rewrite-1 arg var sup-p
,pretty
)))
2097 (labels ((rewrite-1 (arg var sup-p-var pretty
)
2099 (when sup-p-var
(vars (car sup-p-var
)))
2100 (let* ((slot (unless (member var
(aux-vars) :test
#'string
=)
2101 (find var
(dd-slots dd
)
2102 :key
#'dsd-name
:test
#'string
=)))
2103 (default (and slot
(dsd-default slot
))))
2104 ;; If VAR initializes a slot and did not have a default in
2105 ;; the lambda list, and DSD-DEFAULT is not NIL,
2106 ;; then change the lambda-list's default for the variable.
2107 ;; Always prefer to insert (CAR ARG) if ARG was a list
2108 ;; so that (:KEY var) syntax is preserved.
2109 (if (and slot
(not (typep arg
'(cons t cons
)))
2111 `(,(if (consp arg
) (car arg
) var
)
2112 ,(default-value slot pretty
)
2114 arg
))) ; keep it as it was
2115 (make-ll (opt rest keys aux-vars
&optional pretty
)
2116 ;; Can we substitute symbols that are not EQ to symbols
2117 ;; naming slots, so we don't have to compare by STRING= later?
2118 ;; Probably not because other symbols could reference them.
2119 (setq opt
(rewrite opt
() parse-optional-arg-spec pretty
))
2120 (when rest
(vars (car rest
) pretty
))
2121 (setq keys
(rewrite keys
(key) parse-key-arg-spec pretty
))
2122 (dolist (arg aux-vars
)
2124 (sb-c::make-lambda-list
2125 llks nil req opt rest keys
2126 ;; &AUX vars which do not initialize a slot are not mentioned
2127 ;; in the lambda list, though it's not clear what to do if
2128 ;; subsequent bindings refer to the deleted ones.
2129 ;; And worse, what if it's SETQd - is that even legal?
2130 (remove-if (lambda (x) (not (typep x
'(cons t cons
)))) aux
))))
2131 `(,(make-ll opt rest keys
(aux-vars))
2132 (declare (explicit-check)
2133 (sb-c::lambda-list
,(make-ll opt rest keys
(aux-vars) t
)))
2137 (lambda (slot &aux
(name (dsd-name slot
)))
2138 (if (find name
(skipped-vars) :test
#'string
=)
2139 ;; CLHS 3.4.6 Boa Lambda Lists
2140 '.do-not-initialize-slot.
2141 (let* ((type (dsd-type slot
))
2142 (found (member (dsd-name slot
) (vars) :test
#'string
=))
2143 (initform (if found
(car found
) (dsd-default slot
))))
2144 ;; We can ignore the DD-ELEMENT-TYPE
2145 ;; because the container itself will check.
2146 (if (eq type t
) initform
`(the ,type
,initform
)))))
2147 (dd-slots dd
))))))))))
2149 ;;;; instances with ALTERNATE-METACLASS
2151 ;;;; The CMU CL support for structures with ALTERNATE-METACLASS was a
2152 ;;;; fairly general extension embedded in the main DEFSTRUCT code, and
2153 ;;;; the result was an fairly impressive mess as ALTERNATE-METACLASS
2154 ;;;; extension mixed with ANSI CL generality (e.g. :TYPE and :INCLUDE)
2155 ;;;; and CMU CL implementation hairiness (esp. raw slots). This SBCL
2156 ;;;; version is much less ambitious, noticing that ALTERNATE-METACLASS
2157 ;;;; is only used to implement CONDITION, STANDARD-INSTANCE, and
2158 ;;;; GENERIC-FUNCTION, and defining a simple specialized
2159 ;;;; separate-from-DEFSTRUCT macro to provide only enough
2160 ;;;; functionality to support those.
2162 ;;;; KLUDGE: The defining macro here is so specialized that it's ugly
2163 ;;;; in its own way. It also violates once-and-only-once by knowing
2164 ;;;; much about structures and layouts that is already known by the
2165 ;;;; main DEFSTRUCT macro. Hopefully it will go away presently
2166 ;;;; (perhaps when CL:CLASS and SB-PCL:CLASS meet) as per FIXME below.
2167 ;;;; -- WHN 2001-10-28
2169 ;;;; FIXME: There seems to be no good reason to shoehorn CONDITION,
2170 ;;;; STANDARD-INSTANCE, and GENERIC-FUNCTION into mutated structures
2171 ;;;; instead of just implementing them as primitive objects. (This
2172 ;;;; reduced-functionality macro seems pretty close to the
2173 ;;;; functionality of !DEFINE-PRIMITIVE-OBJECT..)
2175 ;;; The complete list of alternate-metaclass DEFSTRUCTs:
2176 ;;; CONDITION SB-KERNEL:INTERPRETED-FUNCTION
2177 ;;; SB-PCL::STANDARD-INSTANCE SB-PCL::STANDARD-FUNCALLABLE-INSTANCE
2178 ;;; SB-PCL::CTOR SB-PCL::%METHOD-FUNCTION
2180 (defun make-dd-with-alternate-metaclass (&key
(class-name (missing-arg))
2181 (superclass-name (missing-arg))
2182 (metaclass-name (missing-arg))
2183 (dd-type (missing-arg))
2184 metaclass-constructor
2186 (let* ((dd (make-defstruct-description class-name
+dd-nullenv
+))
2187 (conc-name (string (gensymify* class-name
"-")))
2189 ;; We do *not* fill in the COPIER-NAME and PREDICATE-NAME
2190 ;; because alternate-metaclass structures can not have either.
2192 ;; We don't fully support inheritance of alternate metaclass stuff,
2193 ;; so sanity check our own code.
2195 (aver (eq superclass-name
't
))
2196 ;; Without compact instance headers, the index starts at 1 for
2197 ;; named slots, because slot 0 is the LAYOUT.
2198 ;; This is the same in ordinary structures too: see (INCF DD-LENGTH)
2199 ;; in PARSE-DEFSTRUCT-NAME-AND-OPTIONS.
2200 ;; With compact instance headers, slot 0 is a data slot.
2201 (incf slot-index sb-vm
:instance-data-start
))
2202 (funcallable-structure
2203 (aver (eq superclass-name
'function
)))
2204 (t (bug "Unknown DD-TYPE in ALTERNATE-METACLASS: ~S" dd-type
)))
2205 (setf (dd-type dd
) dd-type
2206 (dd-alternate-metaclass dd
) (list superclass-name
2208 metaclass-constructor
)
2210 (mapcar (lambda (slot-name)
2211 (multiple-value-bind (slot-name type
)
2212 (if (consp slot-name
)
2213 (values (first slot-name
) (second slot-name
))
2214 (values slot-name t
))
2215 (make-dsd slot-name type
(symbolicate conc-name slot-name
)
2216 (pack-dsd-bits (prog1 slot-index
(incf slot-index
))
2220 (dd-length dd
) slot-index
2221 (dd-bitmap dd
) (calculate-dd-bitmap dd
))
2224 (sb-xc:defmacro
!defstruct-with-alternate-metaclass
2226 (slot-names (missing-arg))
2227 (constructor (missing-arg))
2228 (superclass-name (missing-arg))
2229 (metaclass-name (missing-arg))
2230 (metaclass-constructor (missing-arg))
2231 (dd-type (missing-arg)))
2233 (declare (type list slot-names
))
2234 (declare (type (and symbol
(not null
))
2237 metaclass-constructor
))
2238 (declare (symbol constructor
)) ; NIL for none
2239 (declare (type (member structure funcallable-structure
) dd-type
))
2241 (let ((dd (make-dd-with-alternate-metaclass
2242 :class-name class-name
2243 :slot-names slot-names
2244 :superclass-name superclass-name
2245 :metaclass-name metaclass-name
2246 :metaclass-constructor metaclass-constructor
2249 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
2250 (%compiler-defstruct
',dd
',(!inherits-for-structure dd
))
2251 (when (eq (info :type
:kind
',class-name
) :defined
)
2252 (setf (info :type
:kind
',class-name
) :instance
))
2253 ,@(when (eq metaclass-name
'static-classoid
)
2254 `((declaim (freeze-type ,class-name
)))))
2255 ,@(accessor-definitions dd t
)
2257 (multiple-value-bind (allocate set-layout
)
2260 ;; I think the only nonfuncallable alternate-metaclass structure
2261 ;; is CONDITION, which has its own fancy constructor.
2262 ;; Maybe this should be (bug "Can't happen") ?
2263 (values `(%make-structure-instance-macro
,dd nil
) nil
))
2264 (funcallable-structure
2265 (values `(truly-the ,class-name
2266 (%make-funcallable-instance
,(dd-length dd
)))
2267 `((macrolet ((the-layout ()
2268 (info :type
:compiler-layout
',class-name
)))
2269 (setf (%fun-layout object
) (the-layout)))))))
2270 `((defun ,constructor
(,@(mapcar (lambda (x)
2274 slot-names
) &aux
(object ,allocate
))
2276 ,@(when (and (eq dd-type
'funcallable-structure
)
2277 ;; fmt-control is not an executable function
2278 (neq class-name
'sb-format
::fmt-control
))
2279 '((sb-vm::write-funinstance-prologue object
)))
2280 ,@(mapcar (lambda (dsd)
2281 `(setf (,(dsd-accessor-name dsd
) object
) ,(dsd-name dsd
)))
2284 (!target-defstruct-altmetaclass
',dd
,@(accessor-definitions dd nil
)))))
2286 (defun !target-defstruct-altmetaclass
(&rest args
)
2287 (declare (ignore args
)))
2289 ;;;; finalizing bootstrapping
2291 ;;; Set up DD and LAYOUT for STRUCTURE-OBJECT class itself.
2293 ;;; Ordinary structure classes effectively :INCLUDE STRUCTURE-OBJECT
2294 ;;; when they have no explicit :INCLUDEs, so (1) it needs to be set up
2295 ;;; before we can define ordinary structure classes, and (2) it's
2296 ;;; special enough (and simple enough) that we just build it by hand
2297 ;;; instead of trying to generalize the ordinary DEFSTRUCT code.
2298 (defun !set-up-structure-object-class
()
2299 (let ((dd (make-defstruct-description 'structure-object
+dd-nullenv
+)))
2300 (setf (dd-length dd
) sb-vm
:instance-data-start
)
2301 (%compiler-set-up-layout dd
(vector (find-layout 't
)))))
2302 #+sb-xc-host
(!set-up-structure-object-class
)
2304 (defun find-defstruct-description (name &optional
(errorp t
))
2305 (let* ((classoid (find-classoid name errorp
))
2306 (info (and classoid
(layout-%info
(classoid-layout classoid
)))))
2307 (cond ((defstruct-description-p info
)
2310 (error "No DEFSTRUCT-DESCRIPTION for ~S." name
)))))
2312 (defun structure-instance-accessor-p (name)
2313 (let ((info (info :function
:source-transform name
)))
2315 (defstruct-slot-description-p (cdr info
))
2318 (defun dd-default-constructor (dd)
2319 (let ((ctor (first (dd-constructors dd
))))
2320 (when (typep ctor
'(cons t
(eql :default
)))
2324 (defun %instance-ref
(instance index
)
2325 (let* ((layout (%instance-layout instance
))
2326 (map (layout-index->accessor-map layout
)))
2327 (when (zerop (length map
)) ; construct it on demand
2328 (let ((slots (dd-slots (layout-%info layout
))))
2329 (setf map
(make-array (1+ (reduce #'max slots
:key
#'dsd-index
))
2330 :initial-element nil
)
2331 (layout-index->accessor-map layout
) map
)
2333 (setf (aref map
(dsd-index dsd
)) (dsd-accessor-name dsd
)))))
2334 (funcall (aref map index
) instance
)))
2337 (defun %raw-instance-ref
/word
(instance index
) (%instance-ref instance index
))
2339 ;;; It is possible to produce instances of structure-object which violate
2340 ;;; the assumption throughout the compiler that slot readers are safe
2341 ;;; unless dictated otherwise by the SAFE-P flag in the DSD.
2342 ;;; * (defstruct S a (b (error "Must supply me") :type symbol))
2343 ;;; * (defmethod make-load-form ((x S) &optional e) (m-l-f-s-s x :slot-names '(a)))
2344 ;;; After these definitions, a dumped S will have #<unbound> in slot B.
2345 (defun make-load-form-saving-slots (object &key
(slot-names nil slot-names-p
)
2347 (declare (ignore environment
))
2348 (if (typep object
'structure-object
)
2349 (let ((type (type-of object
)))
2351 (dolist (dsd (dd-slots (layout-dd (%instance-layout object
))))
2352 (declare (type defstruct-slot-description dsd
))
2353 (let ((slot-name (dsd-name dsd
)))
2354 (when (or (memq slot-name slot-names
)
2356 (let* ((accessor (dsd-reader dsd nil
))
2357 (index (dsd-index dsd
))
2358 (value (funcall accessor object index
)))
2359 (inits `(setf (,accessor
,object
,index
) ',value
))))))
2360 (values `(allocate-struct ',(the symbol type
)) ;; no anonymous defstructs
2361 `(progn ,@(inits)))))
2363 (let ((class (class-of object
)))
2365 (dolist (slot (sb-mop:class-slots class
))
2366 (let ((slot-name (sb-mop:slot-definition-name slot
)))
2367 (when (or (memq slot-name slot-names
)
2368 (and (not slot-names-p
)
2369 (eq :instance
(sb-mop:slot-definition-allocation slot
))))
2370 (if (slot-boundp object slot-name
)
2371 (let ((value (slot-value object slot-name
)))
2372 (inits `(setf (slot-value ,object
',slot-name
) ',value
)))
2373 (inits `(slot-makunbound ,object
',slot-name
))))))
2374 (values `(allocate-instance (find-class ',(class-name class
)))
2375 `(progn ,@(inits)))))))
2377 ;;; Compute a SAP to the specified slot in INSTANCE.
2378 ;;; This looks mildly redundant with DEFINE-STRUCTURE-SLOT-ADDRESSOR,
2379 ;;; but that one returns an integer, not a SAP.
2380 (defmacro struct-slot-sap
(instance type-name slot-name
)
2381 `(sap+ (int-sap (get-lisp-obj-address ,instance
))
2382 (- (ash (+ (get-dsd-index ,type-name
,slot-name
) sb-vm
:instance-slots-offset
)
2384 sb-vm
:instance-pointer-lowtag
)))
2387 (defun write-structure-definitions-as-text (pathname)
2388 (with-open-file (output pathname
:direction
:output
:if-exists
:supersede
)
2389 (dolist (root '(structure-object function
))
2390 (dolist (pair (let ((subclassoids (classoid-subclasses (find-classoid root
))))
2391 (if (listp subclassoids
)
2396 (let ((xpn (cl:package-name
(cl:symbol-package x
)))
2397 (ypn (cl:package-name
(cl:symbol-package y
))))
2398 (string< xpn ypn
))))))
2399 (sort (%hash-table-alist subclassoids
)
2401 ;; pair = (#<classoid> . #<layout>)
2402 :key
(lambda (pair) (classoid-name (car pair
))))))))
2403 (let* ((layout (cdr pair
))
2404 (dd (layout-info layout
)))
2407 (let* ((*print-pretty
* nil
) ; output should be insensitive to host pprint
2408 (*print-readably
* t
)
2409 (classoid-name (classoid-name (car pair
)))
2410 (*package
* (cl:symbol-package classoid-name
)))
2411 (format output
"~/sb-ext:print-symbol-with-prefix/ ~S (~%"
2413 (list* (the (unsigned-byte 16) (layout-flags layout
))
2414 (layout-depthoid layout
)
2415 (map 'list
#'layout-classoid-name
2416 (layout-inherits layout
))))
2417 (dolist (dsd (dd-slots dd
) (format output
")~%"))
2418 (format output
" (~d ~S ~S)~%"
2421 (dsd-accessor-name dsd
)))))
2423 (error "Missing DD for ~S" pair
))))))
2424 (format output
";; EOF~%")))
2426 (/show0
"code/defstruct.lisp end of file")