%other-pointer-widetag derive-type: derive for simple-array.
[sbcl.git] / src / code / early-classoid.lisp
blob2a01d0aaa97a3fe668661d6762bbd33ac8424f5f
1 ;;;; This file contains structures and functions for the maintenance of
2 ;;;; basic information about defined types. Different object systems
3 ;;;; can be supported simultaneously.
5 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; more information.
7 ;;;;
8 ;;;; This software is derived from the CMU CL system, which was
9 ;;;; written at Carnegie Mellon University and released into the
10 ;;;; public domain. The software is in the public domain and is
11 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
12 ;;;; files for more information.
14 (in-package "SB-KERNEL")
16 ;;;; DEFSTRUCT-DESCRIPTION
18 (defconstant +dd-named+ #b000001) ; :NAMED was specified
19 (defconstant +dd-printfun+ #b000010) ; :PRINT-FUNCTION was specified
20 (defconstant +dd-printobj+ #b000100) ; :PRINT-OBJECT was specified
21 (defconstant +dd-pure+ #b001000) ; :PURE T was specified
22 (defconstant +dd-varylen+ #b010000)
23 (defconstant +dd-nullenv+ #b100000)
25 ;;; The DEFSTRUCT-DESCRIPTION structure holds compile-time information
26 ;;; about a structure type.
27 ;;; It is defined prior to LAYOUT because a LAYOUT-INFO slot
28 ;;; is declared to hold a DEFSTRUCT-DESCRIPTION.
29 (def!struct (defstruct-description
30 (:conc-name dd-)
31 (:copier nil)
32 (:pure t)
33 (:constructor make-defstruct-description (name flags)))
34 ;; name of the structure
35 (name (missing-arg) :type symbol :read-only t)
36 (flags 0 :type fixnum) ; see the constants above
37 ;; documentation on the structure
38 (doc nil :type (or string null))
39 ;; prefix for slot names. If NIL, none.
40 (conc-name nil :type (or string null))
41 ;; All the :CONSTRUCTOR specs and posssibly an implied constructor,
42 ;; keyword constructors first, then BOA constructors. NIL if none.
43 (constructors () :type list)
44 ;; name of copying function
45 (copier-name nil :type symbol)
46 ;; name of type predicate
47 (predicate-name nil :type symbol)
48 ;; the arguments to the :INCLUDE option, or NIL if no included
49 ;; structure
50 (include nil :type list)
51 ;; properties used to define structure-like classes with an
52 ;; arbitrary superclass and that may not have STRUCTURE-CLASS as the
53 ;; metaclass. Syntax is:
54 ;; (superclass-name metaclass-name metaclass-constructor)
55 (alternate-metaclass nil :type list)
56 ;; a list of DEFSTRUCT-SLOT-DESCRIPTION objects for all slots
57 ;; (including included ones)
58 (slots () :type list)
59 ;; bit mask containing a 1 for each word that the garbage collector must visit
60 ;; (as opposed to a raw slot). Certain slot types (notably fixnum) may have either
61 ;; a 0 or a 1 in the mask because it does not matter if it is seen by GC.
62 ;; Bit index 0 in the mask is the word just after the header, and so on.
63 (bitmap +layout-all-tagged+ :type integer)
64 ;; a list of (NAME . INDEX) pairs for accessors of included structures
65 (inherited-accessor-alist () :type list)
66 ;; number of data words, including the layout itself if the layout
67 ;; requires an entire word (when no immobile-space)
68 ;; Technically this is redundant information: it can be derived from DD-SLOTS
69 ;; by taking the index of the final slot and adding its length in words.
70 ;; If there are no slots, then it's just INSTANCE-DATA-START.
71 (length 0 :type index)
72 ;; General kind of implementation.
73 (type 'structure :type (member structure vector list
74 funcallable-structure))
76 ;; If this structure is a classoid, then T if all slots are tagged, * if not.
77 ;; If a vector, the vector element type.
78 ;; If a list, not used.
79 (%element-type t)
80 ;; any INITIAL-OFFSET option on this direct type
81 (offset nil :type (or index null))
83 ;; the argument to the PRINT-FUNCTION or PRINT-OBJECT option.
84 ;; NIL if the option was given with no argument.
85 (printer-fname nil :type (or cons symbol)))
86 (declaim (freeze-type defstruct-description))
87 (!set-load-form-method defstruct-description (:host :xc :target))
89 ;;;; basic LAYOUT stuff
91 ;;; Careful here: if you add more bits, then adjust the bit packing for
92 ;;; 64-bit layouts which also store LENGTH + DEPTHOID in the same word.
93 (defconstant +structure-layout-flag+ #b000000001)
94 (defconstant +pathname-layout-flag+ #b000000010)
95 (defconstant +pcl-object-layout-flag+ #b000000100)
96 (defconstant +condition-layout-flag+ #b000001000)
97 (defconstant +simple-stream-layout-flag+ #b000010000)
98 (defconstant +file-stream-layout-flag+ #b000100000)
99 (defconstant +string-stream-layout-flag+ #b001000000)
100 (defconstant +stream-layout-flag+ #b010000000)
101 (defconstant +sequence-layout-flag+ #b100000000)
102 (defconstant +strictly-boxed-flag+ #b1000000000)
103 (defconstant layout-flags-mask #xffff) ; "strictly flags" bits from the packed field
105 ;;; the type of LAYOUT-DEPTHOID and LAYOUT-LENGTH values.
106 ;;; Each occupies two bytes of the %BITS slot when possible,
107 ;;; otherwise a slot unto itself.
108 (def!type layout-depthoid () '(integer -1 #x7FFF))
109 (def!type layout-length () '(integer 0 #xFFFF))
110 (def!type layout-bitmap () 'integer)
111 ;;; ID must be an fixnum for either value of n-word-bits.
112 (def!type layout-id () '(signed-byte 30))
114 (declaim (start-block))
116 ;;; The CLASSOID structure is a supertype of all classoid types. A
117 ;;; CLASSOID is also a CTYPE structure as recognized by the type
118 ;;; system. (FIXME: It's also a type specifier, though this might go
119 ;;; away as with the merger of SB-PCL:CLASS and CL:CLASS it's no
120 ;;; longer necessary)
121 (defstruct (classoid
122 (:include ctype)
123 (:constructor nil)
124 (:copier nil)
125 (:print-object
126 (lambda (class stream)
127 (let ((name (classoid-name class)))
128 (print-unreadable-object (class stream
129 :type t
130 :identity (not name))
131 (format stream
132 ;; FIXME: Make sure that this prints
133 ;; reasonably for anonymous classes.
134 "~:[anonymous~;~:*~S~]~@[ (~(~A~))~]"
135 name
136 (classoid-state class))))))
137 #-sb-xc-host (:pure nil))
138 ;;; KLUDGE: Keep synchronized with hardcoded slot order in 'instance.inc'
139 ;; the value to be returned by CLASSOID-NAME.
140 (name nil :type symbol)
141 ;; the current LAYOUT for this class, or NIL if none assigned yet
142 (layout nil :type (or null layout))
143 ;; How sure are we that this class won't be redefined?
144 ;; :READ-ONLY = We are committed to not changing the effective
145 ;; slots or superclasses.
146 ;; :SEALED = We can't even add subclasses.
147 ;; NIL = Anything could happen.
148 (state nil :type (member nil :read-only :sealed))
149 ;; direct superclasses of this class. Always NIL for CLOS classes.
150 (direct-superclasses () :type list)
151 ;; Definition location
152 ;; Not used for standard-classoid, because pcl has its own mechanism.
153 (source-location nil)
154 ;; representation of all of the subclasses (direct or indirect) of
155 ;; this class. This is NIL if no subclasses or not initalized yet;
156 ;; otherwise, it's an EQ hash-table mapping CLASSOID objects to the
157 ;; subclass layout that was in effect at the time the subclass was
158 ;; created.
159 ;; Initially an alist, and changed to a hash-table at some threshold.
160 (subclasses nil :type (or list hash-table))
161 (%lock nil) ; install it just-in-time, similar to hash-table-lock
162 ;; the PCL class (= CL:CLASS, but with a view to future flexibility
163 ;; we don't just call it the CLASS slot) object for this class, or
164 ;; NIL if none assigned yet
165 (pcl-class nil))
167 ;;; The LAYOUT structure is pointed to by the first cell of instance
168 ;;; (or structure) objects. It represents what we need to know for
169 ;;; type checking and garbage collection. Whenever a class is
170 ;;; incompatibly redefined, a new layout is allocated. If two object's
171 ;;; layouts are EQ, then they are exactly the same type.
173 ;;; *** IMPORTANT ***
175 ;;; If you change the slots of LAYOUT, you need to alter genesis as
176 ;;; well, since the initialization of layout slots is hardcoded there.
178 ;;; FIXME: ...it would be better to automate this, of course...
180 ;;; 64-bit layout FLAGS slot:
182 ;;; | 4 bytes | 16 bits | 16 bits |
183 ;;; +----------+---------+---------+
184 ;;; depthoid length flags
186 ;;; depthoid is stored as a tagged fixnum in its 4 byte field.
187 ;;; I suspect that by further limiting the max depthoid and length
188 ;;; we could shove the random CLOS-HASH into some unused bits while
189 ;;; utilizing the entire 64-bit word as the random bit string for hashing.
190 ;;; Checking for an invalid layout would need to mask out the
191 ;;; length, depthoid, and flags since they have to stay correct at all times.
193 ;;; 32-bit layout %BITS slot:
195 ;;; | 2 bytes | 2 bytes |
196 ;;; +---------+---------+
197 ;;; depthoid length
198 ;;; (FLAGS will remain as a separate slot)
200 ;;; 32-bit is not done yet. Three slots are still used, instead of two.
202 (sb-xc:defstruct (layout (:copier nil)
203 ;; Parsing DEFSTRUCT uses a temporary layout
204 (:constructor make-temporary-layout
205 (clos-hash classoid inherits &aux (invalid nil))))
207 ;; A packed field containing the DEPTHOID, LENGTH, and FLAGS
208 #+64-bit (flags 0 :type (signed-byte #.sb-vm:n-word-bits))
210 ;; a union of +something-LAYOUT-FLAG+ bits
211 #-64-bit (flags 0 :type word :read-only nil)
213 ;; a quasi-random hash value for use by CLOS. Determine by class-name
214 ;; for classes named by a symbol, otherwise a pseudo-random value.
215 ;; Must be acceptable as an argument to SB-INT:MIX
216 (clos-hash (missing-arg) :type (and fixnum unsigned-byte))
217 ;; the class that this is a layout for
218 (classoid (missing-arg) :type classoid)
219 ;; The value of this slot can be:
220 ;; * :UNINITIALIZED if not initialized yet;
221 ;; * NIL if this is the up-to-date layout for a class; or
222 ;; * T if this layout has been invalidated (by being replaced by
223 ;; a new, more-up-to-date LAYOUT).
224 ;; * something else (probably a list) if the class is a PCL wrapper
225 ;; and PCL has made it invalid and made a note to itself about it
226 (invalid :uninitialized :type (or cons (member nil t :uninitialized)))
227 ;; the layouts for all classes we inherit. If hierarchical, i.e. if
228 ;; DEPTHOID >= 0, then these are ordered by ORDER-LAYOUT-INHERITS
229 ;; (least to most specific), so that each inherited layout appears
230 ;; at its expected depth, i.e. at its LAYOUT-DEPTHOID value.
232 ;; Remaining elements are filled by the non-hierarchical layouts or,
233 ;; if they would otherwise be empty, by copies of succeeding layouts.
234 (inherits #() :type simple-vector)
235 ;; If inheritance is not hierarchical, this is -1. If inheritance is
236 ;; hierarchical, this is the inheritance depth, i.e. (LENGTH INHERITS).
237 ;; Note:
238 ;; (1) This turns out to be a handy encoding for arithmetically
239 ;; comparing deepness; it is generally useful to do a bare numeric
240 ;; comparison of these depthoid values, and we hardly ever need to
241 ;; test whether the values are negative or not.
242 ;; (2) This was called INHERITANCE-DEPTH in classic CMU CL. It was
243 ;; renamed because some of us find it confusing to call something
244 ;; a depth when it isn't quite.
245 #-64-bit (depthoid -1 :type layout-depthoid)
246 ;; the number of top level descriptor cells in each instance
247 ;; For [FUNCALLABLE-]STANDARD-OBJECT instances, this is the slot vector
248 ;; length, not the primitive object length.
249 ;; I tried making a structure of this many slots, and the compiler blew up;
250 ;; so it's fair to say this limit is sufficient for practical purposes,
251 ;; Let's be consistent here between the two choices of word size.
252 #-64-bit (length 0 :type layout-length) ; smaller than SB-INT:INDEX
253 ;; If this layout has some kind of compiler meta-info, then this is
254 ;; it. If a structure, then we store the DEFSTRUCT-DESCRIPTION here.
255 ;; If this layout is for an object of metatype STANDARD-CLASS,
256 ;; then these are the EFFECTIVE-SLOT-DEFINITION metaobjects.
257 ;; The two are mutually exclusive.
258 (%info nil :type (or list defstruct-description))
259 ;; EQUALP comparator for two instances with this layout
260 ;; Could be the generalized function, or a type-specific one
261 ;; if the defstruct was compiled in a policy of SPEED 3.
262 (equalp-impl #'equalp-err :type (sfunction (t t) boolean) :read-only t)
263 ;; Information for the quicker variant of SLOT-VALUE on STRUCTURE-OBJECT
264 ;; INSTANCE uses at most 14 bits in the primitive object header for the payload
265 ;; length, so the function can't actually return all of the INDEX type.
266 (slot-mapper nil :type (or (sfunction (symbol) (or index null))
267 simple-vector null))
268 ;; Information about slots in the class to PCL: this provides fast
269 ;; access to slot-definitions and locations by name, etc.
270 ;; See MAKE-SLOT-TABLE in pcl/slots-boot.lisp for further details.
271 (slot-table #(1 nil) :type simple-vector)
272 (id-word0 0 :type word)
273 (id-word1 0 :type word)
274 (id-word2 0 :type word)
275 #-64-bit (id-word3 0 :type word)
276 #-64-bit (id-word4 0 :type word)
277 #-64-bit (id-word5 0 :type word))
278 (declaim (freeze-type layout))
280 (declaim (end-block))
282 ;;; The cross-compiler representation of a LAYOUT omits several things:
283 ;;; * BITMAP - obtainable via (DD-BITMAP (LAYOUT-INFO layout)).
284 ;;; GC wants it in the layout to avoid double indirection.
285 ;;; * EQUALP-TESTS - needed only for the target's implementation of EQUALP.
286 ;;; * SLOT-TABLE, and SLOT-LIST - used only by the CLOS implementation.
287 ;;; * ID-WORDn are optimizations for TYPEP.
288 ;;; So none of those really make sense on the host.
289 ;;; Also, we eschew the packed representation of length+depthoid+flags.
290 ;;; FLAGS are computed on demand, and not stored.
291 #+sb-xc-host
292 (progn
293 (defstruct (layout (:constructor host-make-layout
294 (id clos-hash classoid
295 &key ((:info %info)) depthoid inherits length invalid)))
296 (id nil :type (or null fixnum))
297 ;; Cross-compiler-only translation from slot index to symbol naming
298 ;; the accessor to call. (Since access by position is not a thing)
299 (index->accessor-map #() :type simple-vector)
300 ;; CLOS-HASH is needed to convert some TYPECASE forms to jump tables.
301 ;; Theoretically we don't need this in the cross-compiler, because the
302 ;; layout has a classoid which has a name which has a known hash.
303 ;; But there's no harm in storing it.
304 (clos-hash nil :type (and sb-xc:fixnum unsigned-byte))
305 (classoid nil :type classoid)
306 (invalid :uninitialized :type (or cons (member nil t :uninitialized)))
307 (inherits #() :type simple-vector)
308 (depthoid -1 :type layout-depthoid)
309 (length 0 :type layout-length)
310 (%info nil :type (or null defstruct-description)))
311 (defun make-temporary-layout (clos-hash classoid inherits)
312 (host-make-layout nil clos-hash classoid :inherits inherits :invalid nil))
313 (defun layout-flags (layout)
314 (declare (type layout layout))
315 (let ((mapping `((structure-object ,+structure-layout-flag+)
316 (standard-object ,+pcl-object-layout-flag+)
317 (pathname ,+pathname-layout-flag+)
318 (condition ,+condition-layout-flag+)
319 (file-stream ,+file-stream-layout-flag+)
320 (string-stream ,+string-stream-layout-flag+)
321 (stream ,+stream-layout-flag+)
322 (sequence ,+sequence-layout-flag+)))
323 (flags 0))
324 (dolist (x (cons layout (coerce (layout-inherits layout) 'list)))
325 (let ((cell (assoc (layout-classoid-name x) mapping)))
326 (when cell (setq flags (logior flags (second cell))))))
327 (let ((dd (layout-%info layout)))
328 (when (or (logtest flags (logior +pathname-layout-flag+ +condition-layout-flag+))
329 (and (logtest flags +structure-layout-flag+)
331 (eq (dd-%element-type dd) 't)))
332 (setf flags (logior flags +strictly-boxed-flag+))))
333 ;; KLUDGE: I really don't care to make defstruct-with-alternate-metaclass
334 ;; any more complicated than necessary. It is unable to express that
335 ;; these funcallable instances can go on pure boxed pages.
336 ;; (The trampoline is always an assembler routine, thus ignorable)
337 (when (member (layout-classoid-name layout)
338 '(sb-pcl::ctor sb-pcl::%method-function))
339 (setf flags (logior flags +strictly-boxed-flag+)))
340 flags))
341 (defun layout-bitmap (layout)
342 (acond ((layout-%info layout) (dd-bitmap it))
343 ;; Give T a 0 bitmap. It's arbitrary, but when we need some layout
344 ;; that has this bitmap we can use the layout of T.
345 ((eq layout (find-layout t)) 0)
346 ;; KLUDGE: PROMISE-COMPILE stuffs the layout of FUNCTION into the
347 ;; funcallable-instance it produces. gencgc verifies that funcallable-instances
348 ;; have a bitmap with 0 bits where the trampoline word and layout are.
349 #-compact-instance-header ((eq layout (find-layout 'function)) -4)
351 +layout-all-tagged+)))
352 (defun %layout-bitmap (layout) (layout-bitmap layout))
353 ) ; end PROGN #+sb-xc-host
355 (defun equalp-err (a b)
356 (bug "EQUALP ~S ~S" a b))
358 (defmacro get-dsd-index (type-name slot-name)
359 (declare (notinline dsd-index)) ; avoid later inlining failure style-warning
360 (dsd-index (find slot-name
361 (dd-slots (find-defstruct-description type-name))
362 :key #'dsd-name)))
364 ;;; Applicable only if bit-packed (for 64-bit architectures)
365 (defmacro pack-layout-flags (depthoid length flags)
366 `(logior (ash ,depthoid (+ 32 sb-vm:n-fixnum-tag-bits)) (ash ,length 16) ,flags))
368 (defmacro type-dd-length (type-name)
369 (dd-length (find-defstruct-description type-name)))
371 (defconstant layout-id-vector-fixed-capacity 7)
372 (defmacro calculate-extra-id-words (depthoid)
373 ;; There are 1 or 2 ids per word depending on n-word-bytes.
374 ;; We can always store IDs at depthoids 2,3,4,5,6,7,
375 ;; so depthoid less than or equal to 7 needs no extra words.
376 ;; 0 and 1 for T and STRUCTURE-OBJECT respectively are not stored.
377 `(ceiling (max 0 (- ,depthoid ,layout-id-vector-fixed-capacity))
378 ,(/ sb-vm:n-word-bytes 4)))
380 (declaim (inline layout-dd layout-info))
381 ;; Use LAYOUT-DD to read LAYOUT-INFO if you want to assert that it is non-nil.
382 (defun layout-dd (layout)
383 (the defstruct-description (layout-%info layout)))
384 (defun layout-info (layout)
385 (let ((info (layout-%info layout)))
386 (unless (listp info) info)))
387 (defun (setf layout-info) (newval layout)
388 ;; The current value must be nil or a defstruct-description,
389 ;; otherwise we'd clobber a non-nil slot list.
390 (aver (not (consp (layout-%info layout))))
391 (setf (layout-%info layout) newval))
393 #-sb-xc-host
394 (progn
395 (declaim (inline bitmap-start bitmap-nwords bitmap-all-taggedp))
396 (defun bitmap-start (layout)
397 (+ (type-dd-length layout)
398 (calculate-extra-id-words (layout-depthoid layout))))
399 (defun bitmap-nwords (layout)
400 (declare (layout layout))
401 (- (%instance-length layout)
402 (calculate-extra-id-words (layout-depthoid layout))
403 (type-dd-length layout)))
404 (defun bitmap-all-taggedp (layout)
405 ;; All bitmaps have at least 1 word; read that first.
406 (and (= (%raw-instance-ref/signed-word layout (bitmap-start layout))
407 +layout-all-tagged+)
408 ;; Then check that there are no additional words.
409 (= (bitmap-nwords layout) 1)))
410 #+64-bit
411 (defmacro layout-length (layout) ; SETFable
412 `(ldb (byte 16 16) (layout-flags ,layout)))
413 ) ; end PROGN #-sb-xc-host
415 ;;; True of STANDARD-OBJECT, which include generic functions.
416 (declaim (inline layout-for-pcl-obj-p))
417 (defun layout-for-pcl-obj-p (layout)
418 (declare (type layout layout))
419 (logtest (layout-flags layout) +pcl-object-layout-flag+))
421 (defun layout-classoid-name (x)
422 (classoid-name (layout-classoid x)))
424 ;;;; object types to represent classes
426 ;;; An UNDEFINED-CLASSOID is a cookie we make up to stick in forward
427 ;;; referenced layouts. Users should never see them.
428 (defstruct (undefined-classoid
429 (:include classoid)
430 (:constructor !alloc-undefined-classoid (%bits name))
431 (:copier nil)))
433 ;;; BUILT-IN-CLASS is used to represent the standard classes that
434 ;;; aren't defined with DEFSTRUCT and other specially implemented
435 ;;; primitive types whose only attribute is their name.
437 ;;; Some BUILT-IN-CLASSes have a TRANSLATION, which means that they
438 ;;; are effectively DEFTYPE'd to some other type (usually a union of
439 ;;; other classes or a "primitive" type such as NUMBER, ARRAY, etc.)
440 ;;; This translation is done when type specifiers are parsed. Type
441 ;;; system operations (union, subtypep, etc.) should never encounter
442 ;;; translated classes, only their translation.
443 (defstruct (built-in-classoid (:include classoid) (:copier nil)
444 (:constructor !make-built-in-classoid))
445 ;; the type we translate to on parsing. If NIL, then this class
446 ;; stands on its own. Only :INITIALIZING for a period during cold
447 ;; load.
448 (translation nil :type (or null ctype (member :initializing)))
449 (predicate (missing-arg) :type (sfunction (t) boolean) :read-only t))
451 (defstruct (condition-classoid (:include classoid)
452 (:constructor !alloc-condition-classoid (%bits name))
453 (:copier nil))
454 ;; list of CONDITION-SLOT structures for the direct slots of this
455 ;; class
456 (slots nil :type list)
457 ;; list of CONDITION-SLOT structures for all of the effective class
458 ;; slots of this class
459 (class-slots nil :type list)
460 ;; report function or NIL
461 (report nil :type (or function null))
462 ;; list of specifications of the form
464 ;; (INITARG INITFORM THUNK)
466 ;; where THUNK, when called without arguments, returns the value for
467 ;; INITARG.
468 (direct-default-initargs () :type list)
469 ;; class precedence list as a list of CLASS objects, with all
470 ;; non-CONDITION classes removed
471 (cpl () :type list)
472 ;; a list of all the effective instance allocation slots of this
473 ;; class that have a non-constant initform or default-initarg.
474 ;; Values for these slots must be computed in the dynamic
475 ;; environment of MAKE-CONDITION.
476 (hairy-slots nil :type list))
478 ;;; STRUCTURE-CLASSOID represents what we need to know about structure
479 ;;; classes. Non-structure "typed" defstructs are a special case, and
480 ;;; don't have a corresponding class.
481 (defstruct (structure-classoid
482 (:include classoid)
483 (:constructor !alloc-structure-classoid (%bits name))
484 (:copier nil)))
486 ;;;; classoid namespace
488 ;;; We use an indirection to allow forward referencing of class
489 ;;; definitions with load-time resolution.
490 (defstruct (classoid-cell
491 (:copier nil)
492 (:constructor make-classoid-cell (name &optional classoid))
493 (:print-object (lambda (s stream)
494 (print-unreadable-object (s stream :type t)
495 (prin1 (classoid-cell-name s) stream)))))
496 ;; Name of class we expect to find.
497 (name nil :type symbol :read-only t)
498 ;; Classoid or NIL if not yet defined.
499 (classoid nil :type (or classoid null))
500 ;; PCL class, if any
501 (pcl-class nil))
502 (declaim (freeze-type classoid-cell))
503 (!set-load-form-method classoid-cell (:xc :target)
504 (lambda (self env)
505 (declare (ignore env))
506 `(find-classoid-cell ',(classoid-cell-name self) :create t)))
508 ;;;; PCL stuff
510 ;;; the CLASSOID that we use to represent type information for
511 ;;; STANDARD-CLASS and FUNCALLABLE-STANDARD-CLASS. The type system
512 ;;; side does not need to distinguish between STANDARD-CLASS and
513 ;;; FUNCALLABLE-STANDARD-CLASS.
514 (defstruct (standard-classoid
515 (:include classoid)
516 (:constructor !alloc-standard-classoid (%bits name pcl-class))
517 (:copier nil))
518 old-layouts)
519 ;;; a metaclass for classes which aren't standardlike but will never
520 ;;; change either.
521 (defstruct (static-classoid (:include classoid)
522 (:constructor !alloc-static-classoid (%bits name))
523 (:copier nil)))
525 (declaim (freeze-type built-in-classoid condition-classoid
526 standard-classoid static-classoid))
528 ;;; Return the name of the global hashset that OBJ (a CTYPE instance)
529 ;;; would be stored in, if it were stored in one.
530 ;;; This is only for bootstrap, and not 100% precise as it does not know
531 ;;; about *EQL-TYPE-CACHE* or *MEMBER/EQ-TYPE-HASHSET*
532 (defun ctype->hashset-sym (obj)
533 (macrolet ((generate ()
534 (collect ((clauses))
535 (dolist (type-class *type-class-list*)
536 (dolist (instance-type (cdr type-class))
537 (clauses
538 (cons instance-type
539 (unless (member instance-type '(classoid named-type))
540 (symbolicate "*" instance-type "-HASHSET*"))))))
541 #+sb-xc-host
542 `(etypecase obj
543 ,@(mapcar (lambda (x) `(,(car x) ',(cdr x))) (clauses)))
544 ;; For cold-init, we need something guaranteed to work no matter the expansion
545 ;; of TYPEP. If this is called too early, then the optimized code for TYPEP
546 ;; (whatever it is) may fail. But Genesis is able to externalize an alist that
547 ;; maps #<layout> to symbol, and it's mostly ok to compare layouts by EQ here,
548 ;; but it fails on CLASSOID's subtypes, so recognize those specially.
549 #-sb-xc-host
550 (let ((alist (mapcar (lambda (x) (cons (find-layout (car x)) (cdr x)))
551 (clauses))))
552 `(let ((cell (assoc (%instance-layout obj) ',alist)))
553 (cond (cell (cdr cell))
554 ((classoid-p obj) nil)
555 (t (bug "ctype dumping problem"))))))))
556 (generate)))
558 (declaim (freeze-type ctype))
560 ;;; Anything which performs TYPECASE over the type metatypes should occur
561 ;;; after all sructures are frozen, otherwise we'll use the inefficient
562 ;;; expansion of TYPECASE
563 ;;; Copy X to the heap, give it a random hash, and if it is a MEMBER type
564 ;;; then assert that all members are cacheable.
565 #+sb-xc-host
566 (defun copy-ctype (x)
567 (let ((bits (logior (type-%bits x) (logand (ctype-random) +ctype-hash-mask+))))
568 (etypecase x
569 (member-type
570 (!alloc-member-type bits (member-type-xset x) (member-type-fp-zeroes x))))))
571 #-sb-xc-host
572 (defun copy-ctype (x &optional (flags 0))
573 (declare (type ctype x))
574 (declare (sb-c::tlab :system) (inline !new-xset))
575 #+c-stack-is-control-stack (aver (stack-allocated-p x))
576 (labels ((copy (x)
577 ;; Return a heap copy of X if X was arena or stack-allocated.
578 ;; I suspect it's quicker to copy always rather than conditionally.
579 ;; The use for this is that supposing the user constructs a type specifier
580 ;; like (DOUBLE-FLOAT (2.0) 4.0) where those numbers and the inner list
581 ;; were constructed on an arena, they need to be copied.
582 (etypecase x
583 (number (sb-vm:copy-number-to-heap x))
584 (cons (cons (copy (car x)) (copy (cdr x))))
585 (symbol x)))
586 (copy-xset (xset &aux (data (xset-data xset)))
587 ;; MEMBER-TYPE is a problem because the members could be arena-allocated.
588 ;; It would be easy enough to avoid entering some instances in a hashset, though
589 ;; the larger issue is that it may be inserted into any number of other caches.
590 ;; CLHS never says whether DX objects are or aren't legal in type specifiers.
591 ;; I consider this "user error" as it seems to push the boundary of what should
592 ;; be permissible, but we can do better than to cache data that are on the stack.
593 ;; If the XSET is represented as a hash-table, we may have another issue
594 ;; which is not dealt with here (hash-table in the arena)
595 (cond ((listp data)
596 ;; the XSET can be empty if a MEMBER type contains only FP zeros.
597 ;; While we could use (load-time-value) to referece a constant empty xset
598 ;; there's really no point to doing that.
599 (collect ((elts))
600 (dolist (x data (!new-xset (elts) (xset-extra xset)))
601 (elts (cond ((numberp x) (sb-vm:copy-number-to-heap x))
602 ((safe-member-type-elt-p x) x)
603 ;; surely things will go haywire if this occurs
604 (t (error "Off-heap MEMBER type member @ ~X"
605 (get-lisp-obj-address x))))))))
606 ;; Huge MEMBER types are rare so I'm not going to worry too much,
607 ;; just check whether it's OK or not
608 ((and (loop for k being each hash-key of data
609 always (safe-member-type-elt-p k))
610 (heap-allocated-p data))
611 xset)
612 (t ; This could certainly be improved
613 (error "Off-heap MEMBER type members")))))
614 (let ((bits (logior (type-%bits x) (logand (ctype-random) +ctype-hash-mask+) flags)))
615 ;; These cases are in descending order of frequency of seek in the hashsets.
616 ;; It matters only for backends that don't convert TYPECASE to a jump table.
617 (etypecase x
618 (values-type
619 (!alloc-values-type bits (values-type-required x) (values-type-optional x)
620 (values-type-rest x)))
621 (fun-type ; or FUN-DESIGNATOR-TYPE
622 (let ((copy (!alloc-fun-type
623 bits (fun-type-required x) (fun-type-optional x) (fun-type-rest x)
624 (fun-type-keyp x) (fun-type-keywords x) (fun-type-allowp x)
625 (fun-type-wild-args x) (fun-type-returns x))))
626 (%set-instance-layout copy (%instance-layout x))
627 copy))
628 (numeric-type
629 (!alloc-numeric-type bits (numeric-type-aspects x)
630 (copy (numeric-type-low x)) (copy (numeric-type-high x))))
631 (compound-type ; UNION or INTERSECTION
632 (let ((copy (!alloc-union-type bits (compound-type-enumerable x)
633 (compound-type-types x))))
634 (%set-instance-layout copy (%instance-layout x))
635 copy))
636 (member-type
637 (!alloc-member-type bits (copy-xset (member-type-xset x))
638 (mapcar 'sb-vm:copy-number-to-heap (member-type-fp-zeroes x))))
639 (array-type
640 (!alloc-array-type bits (copy (array-type-dimensions x))
641 (array-type-complexp x) (array-type-element-type x)
642 (array-type-specialized-element-type x)))
643 (hairy-type ; SATISFIES or UNKNOWN
644 (let ((copy (!alloc-hairy-type bits (copy (hairy-type-specifier x)))))
645 (%set-instance-layout copy (%instance-layout x))
646 copy))
647 (negation-type (!alloc-negation-type bits (negation-type-type x)))
648 (constant-type (!alloc-constant-type bits (constant-type-type x)))
649 (cons-type (!alloc-cons-type bits (cons-type-car-type x) (cons-type-cdr-type x)))
650 (character-set-type
651 (!alloc-character-set-type bits (copy (character-set-type-pairs x))))
652 #+sb-simd-pack
653 (simd-pack-type (!alloc-simd-pack-type bits (simd-pack-type-tag-mask x)))
654 #+sb-simd-pack-256
655 (simd-pack-256-type (!alloc-simd-pack-256-type bits (simd-pack-256-type-tag-mask x)))
656 (alien-type-type (!alloc-alien-type-type bits (alien-type-type-alien-type x)))))))
658 #-sb-xc-host
659 (progn
660 (defglobal *!initial-ctypes* nil)
661 (defun preload-ctype-hashsets ()
662 (dolist (pair (nreverse *!initial-ctypes*))
663 (let ((instance (car pair))
664 (container (symbol-value (cdr pair))))
665 (cond ((hash-table-p container)
666 (aver (member-type-p instance))
667 ;; As of this writing there are only two EQL types to preload:
668 ;; one is in the IR1-transform of FORMAT with stream (EQL T),
669 ;; the other is CHECK-ARG-TYPE looking for (EQL DUMMY) type.
670 (let ((key (first (member-type-members instance))))
671 (aver (not (gethash key container)))
672 (setf (gethash key container) instance)))
674 (aver (not (hashset-find container instance))) ; instances are built bottom-up
675 (hashset-insert container instance)))
676 (labels ((ensure-interned-list (list hashset)
677 (let ((found (hashset-find hashset list)))
678 (when (and found (neq found list))
679 (bug "genesis failed to uniquify list-of-ctype in ~X"
680 (get-lisp-obj-address instance)))
681 (when (and list (not found))
682 (hashset-insert hashset list)))
683 (mapc #'check list))
684 ;; Assert that looking for SUBPART finds nothing or finds itself
685 (check (subpart &aux (hashset-symbol (ctype->hashset-sym subpart)))
686 (when hashset-symbol
687 (let* ((hashset (symbol-value hashset-symbol))
688 (found (hashset-find hashset subpart)))
689 (when (and found (neq found subpart))
690 (bug "genesis dumped bad instance within ~X"
691 (get-lisp-obj-address instance)))))))
692 (etypecase instance
693 ((or numeric-type member-type character-set-type ; nothing extra to do
694 #+sb-simd-pack simd-pack-type #+sb-simd-pack-256 simd-pack-256-type
695 hairy-type))
696 (args-type
697 (ensure-interned-list (args-type-required instance) *ctype-list-hashset*)
698 (ensure-interned-list (args-type-optional instance) *ctype-list-hashset*)
699 (awhen (args-type-rest instance) (check it))
700 (when (fun-type-p instance)
701 (aver (null (fun-type-keywords instance)))
702 (check (fun-type-returns instance))))
703 (cons-type
704 (check (cons-type-car-type instance))
705 (check (cons-type-cdr-type instance)))
706 (array-type
707 (check (array-type-element-type instance))
708 (check (array-type-specialized-element-type instance)))
709 (compound-type
710 (ensure-interned-list (compound-type-types instance) *ctype-set-hashset*))
711 (negation-type
712 (check (negation-type-type instance)))))))
713 #+sb-devel (setq *hashsets-preloaded* t))
714 (preload-ctype-hashsets))