1 ;;;; This file defines the optimized make-instance functions.
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from software originally released by Xerox
7 ;;;; Corporation. Copyright and release statements follow. Later modifications
8 ;;;; to the software are in the public domain and are provided with
9 ;;;; absolutely no warranty. See the COPYING and CREDITS files for more
12 ;;;; copyright information from original PCL sources:
14 ;;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
15 ;;;; All rights reserved.
17 ;;;; Use and copying of this software and preparation of derivative works based
18 ;;;; upon this software are permitted. Any distribution of this software or
19 ;;;; derivative works must comply with all applicable United States export
22 ;;;; This software is made available AS IS, and Xerox Corporation makes no
23 ;;;; warranty about the software, its performance or its conformity to any
28 (defvar *compile-make-instance-functions-p* nil)
30 (defun update-make-instance-function-table (&optional (class *the-class-t*))
31 (when (symbolp class) (setq class (find-class class)))
32 (when (eq class *the-class-t*) (setq class *the-class-slot-object*))
33 (when (memq *the-class-slot-object* (class-precedence-list class))
34 (map-all-classes #'reset-class-initialize-info class)))
36 (defun constant-symbol-p (form)
38 (let ((object (eval form)))
40 (symbol-package object)))))
42 (defvar *make-instance-function-keys* nil)
44 (defun expand-make-instance-form (form)
45 (let ((class (cadr form)) (initargs (cddr form))
46 (keys nil)(allow-other-keys-p nil) key value)
47 (when (and (constant-symbol-p class)
48 (let ((initargs-tail initargs))
49 (loop (when (null initargs-tail) (return t))
50 (unless (constant-symbol-p (car initargs-tail))
52 (setq key (eval (pop initargs-tail)))
53 (setq value (pop initargs-tail))
54 (when (eq ':allow-other-keys key)
55 (setq allow-other-keys-p value))
57 (let* ((class (eval class))
58 (keys (nreverse keys))
59 (key (list class keys allow-other-keys-p))
60 (sym (make-instance-function-symbol key)))
61 (push key *make-instance-function-keys*)
63 `(,sym ',class (list ,@initargs)))))))
65 (defmacro expanding-make-instance-top-level (&rest forms &environment env)
66 (let* ((*make-instance-function-keys* nil)
67 (form (macroexpand `(expanding-make-instance ,@forms) env)))
69 ,@(when *make-instance-function-keys*
70 `((get-make-instance-functions ',*make-instance-function-keys*)))
73 (defmacro expanding-make-instance (&rest forms &environment env)
75 ,@(mapcar #'(lambda (form)
77 #'(lambda (subform context env)
78 (declare (ignore env))
79 (or (and (eq context ':eval)
81 (eq (car subform) 'make-instance)
82 (expand-make-instance-form subform))
86 (defmacro defconstructor
87 (name class lambda-list &rest initialization-arguments)
88 `(expanding-make-instance-top-level
89 (defun ,name ,lambda-list
90 (make-instance ',class ,@initialization-arguments))))
92 (defun get-make-instance-functions (key-list)
93 (dolist (key key-list)
94 (let* ((cell (find-class-cell (car key)))
95 (make-instance-function-keys
96 (find-class-cell-make-instance-function-keys cell))
97 (mif-key (cons (cadr key) (caddr key))))
98 (unless (find mif-key make-instance-function-keys
100 (push mif-key (find-class-cell-make-instance-function-keys cell))
101 (let ((class (find-class-cell-class cell)))
102 (when (and class (not (forward-referenced-class-p class)))
103 (update-initialize-info-internal
104 (initialize-info class (car mif-key) nil (cdr mif-key))
105 'make-instance-function)))))))
107 (defun make-instance-function-symbol (key)
108 (let* ((class (car key))
109 (symbolp (symbolp class)))
110 (when (or symbolp (classp class))
111 (let* ((class-name (if (symbolp class) class (class-name class)))
113 (allow-other-keys-p (caddr key)))
114 (when (and (or symbolp
115 (and (symbolp class-name)
116 (eq class (find-class class-name nil))))
117 (symbol-package class-name))
118 (let ((*package* *pcl-package*)
122 (*print-case* :upcase)
123 (*print-pretty* nil))
125 "MAKE-INSTANCE ~S ~S ~S"
128 allow-other-keys-p))))))))
130 (defun make-instance-1 (class initargs)
131 (apply #'make-instance class initargs))
133 (defmacro define-cached-reader (type name trap)
134 (let ((reader-name (intern (format nil "~A-~A" type name)))
135 (cached-name (intern (format nil "~A-CACHED-~A" type name))))
136 `(defmacro ,reader-name (info)
137 `(let ((value (,',cached-name ,info)))
138 (if (eq value ':unknown)
140 (,',trap ,info ',',name)
141 (,',cached-name ,info))
144 (eval-when (:compile-toplevel :load-toplevel :execute)
145 (defparameter *initialize-info-cached-slots*
146 '(valid-p ; t or (:invalid key)
150 default-initargs-function
151 shared-initialize-t-function
152 shared-initialize-nil-function
154 combined-initialize-function ; allocate-instance + shared-initialize
155 make-instance-function ; nil means use gf
156 make-instance-function-symbol)))
158 (defmacro define-initialize-info ()
159 (let ((cached-slot-names
160 (mapcar #'(lambda (name)
161 (intern (format nil "CACHED-~A" name)))
162 *initialize-info-cached-slots*))
164 (mapcar #'(lambda (name)
165 (intern (format nil "~A-CACHED-~A"
166 'initialize-info name)))
167 *initialize-info-cached-slots*)))
169 (defstruct initialize-info
171 ,@(mapcar #'(lambda (name)
174 (defmacro reset-initialize-info-internal (info)
176 ,@(mapcar #'(lambda (cname)
177 `(setf (,cname ,info) ':unknown))
179 (defun initialize-info-bound-slots (info)
181 ,@(mapcar #'(lambda (name cached-name)
182 `(unless (eq ':unknown (,cached-name info))
183 (push ',name slots)))
184 *initialize-info-cached-slots* cached-names)
186 ,@(mapcar #'(lambda (name)
187 `(define-cached-reader initialize-info ,name
188 update-initialize-info-internal))
189 *initialize-info-cached-slots*))))
191 (define-initialize-info)
193 (defvar *initialize-info-cache-class* nil)
194 (defvar *initialize-info-cache-initargs* nil)
195 (defvar *initialize-info-cache-info* nil)
197 (defvar *revert-initialize-info-p* nil)
199 (defun reset-initialize-info (info)
200 (setf (initialize-info-wrapper info)
201 (class-wrapper (car (initialize-info-key info))))
202 (let ((slots-to-revert (if *revert-initialize-info-p*
203 (initialize-info-bound-slots info)
204 '(make-instance-function))))
205 (reset-initialize-info-internal info)
206 (dolist (slot slots-to-revert)
207 (update-initialize-info-internal info slot))
210 (defun reset-class-initialize-info (class)
211 (reset-class-initialize-info-1 (class-initialize-info class)))
213 (defun reset-class-initialize-info-1 (cell)
216 (reset-initialize-info (car cell)))
217 (let ((alist (cdr cell)))
219 (reset-class-initialize-info-1 (cdr a))))))
221 (defun initialize-info (class
225 allow-other-keys-arg)
227 (if (and (eq *initialize-info-cache-class* class)
228 (eq *initialize-info-cache-initargs* initargs))
229 (setq info *initialize-info-cache-info*)
230 (let ((initargs-tail initargs)
231 (cell (or (class-initialize-info class)
232 (setf (class-initialize-info class) (cons nil nil)))))
233 (loop (when (null initargs-tail) (return nil))
234 (let ((keyword (pop initargs-tail))
237 (if (eq keyword :allow-other-keys)
238 (setq allow-other-keys-arg (pop initargs-tail))
239 (pop initargs-tail)))
240 (loop (let ((alist (cdr alist-cell)))
242 (setq cell (cons nil nil))
243 (setf (cdr alist-cell) (list (cons keyword cell)))
245 (when (eql keyword (caar alist))
246 (setq cell (cdar alist))
248 (setq alist-cell alist)))))
249 (setq info (or (car cell)
250 (setf (car cell) (make-initialize-info))))))
251 (let ((wrapper (initialize-info-wrapper info)))
252 (unless (eq wrapper (class-wrapper class))
254 (let* ((initargs-tail initargs)
255 (klist-cell (list nil))
256 (klist-tail klist-cell))
257 (loop (when (null initargs-tail) (return nil))
258 (let ((key (pop initargs-tail)))
259 (setf (cdr klist-tail) (list key)))
260 (setf klist-tail (cdr klist-tail))
261 (when plist-p (pop initargs-tail)))
262 (setf (initialize-info-key info)
263 (list class (cdr klist-cell) allow-other-keys-arg))))
264 (reset-initialize-info info)))
265 (setq *initialize-info-cache-class* class)
266 (setq *initialize-info-cache-initargs* initargs)
267 (setq *initialize-info-cache-info* info)
270 (defun update-initialize-info-internal (info name)
271 (let* ((key (initialize-info-key info))
274 (allow-other-keys-arg (caddr key)))
276 ((initargs-form-list new-keys)
277 (multiple-value-bind (initargs-form-list new-keys)
278 (make-default-initargs-form-list class keys)
279 (setf (initialize-info-cached-initargs-form-list info)
281 (setf (initialize-info-cached-new-keys info) new-keys)))
282 ((default-initargs-function)
283 (let ((initargs-form-list (initialize-info-initargs-form-list info)))
284 (setf (initialize-info-cached-default-initargs-function info)
285 (initialize-instance-simple-function
286 'default-initargs-function info
287 class initargs-form-list))))
288 ((valid-p ri-valid-p)
289 (flet ((compute-valid-p (methods)
290 (or (not (null allow-other-keys-arg))
291 (multiple-value-bind (legal allow-other-keys)
292 (check-initargs-values class methods)
293 (or (not (null allow-other-keys))
295 (unless (member key legal)
296 (return (cons :invalid key)))))))))
297 (let ((proto (class-prototype class)))
298 (setf (initialize-info-cached-valid-p info)
300 (list (list* 'allocate-instance class nil)
301 (list* 'initialize-instance proto nil)
302 (list* 'shared-initialize proto t nil))))
303 (setf (initialize-info-cached-ri-valid-p info)
305 (list (list* 'reinitialize-instance proto nil)
306 (list* 'shared-initialize proto nil nil)))))))
307 ((shared-initialize-t-function)
308 (multiple-value-bind (initialize-form-list ignore)
309 (make-shared-initialize-form-list class keys t nil)
310 (declare (ignore ignore))
311 (setf (initialize-info-cached-shared-initialize-t-function info)
312 (initialize-instance-simple-function
313 'shared-initialize-t-function info
314 class initialize-form-list))))
315 ((shared-initialize-nil-function)
316 (multiple-value-bind (initialize-form-list ignore)
317 (make-shared-initialize-form-list class keys nil nil)
318 (declare (ignore ignore))
319 (setf (initialize-info-cached-shared-initialize-nil-function info)
320 (initialize-instance-simple-function
321 'shared-initialize-nil-function info
322 class initialize-form-list))))
323 ((constants combined-initialize-function)
324 (let ((initargs-form-list (initialize-info-initargs-form-list info))
325 (new-keys (initialize-info-new-keys info)))
326 (multiple-value-bind (initialize-form-list constants)
327 (make-shared-initialize-form-list class new-keys t t)
328 (setf (initialize-info-cached-constants info) constants)
329 (setf (initialize-info-cached-combined-initialize-function info)
330 (initialize-instance-simple-function
331 'combined-initialize-function info
332 class (append initargs-form-list initialize-form-list))))))
333 ((make-instance-function-symbol)
334 (setf (initialize-info-cached-make-instance-function-symbol info)
335 (make-instance-function-symbol key)))
336 ((make-instance-function)
337 (let* ((function (get-make-instance-function key))
338 (symbol (initialize-info-make-instance-function-symbol info)))
339 (setf (initialize-info-cached-make-instance-function info) function)
340 (when symbol (setf (gdefinition symbol)
341 (or function #'make-instance-1)))))))
344 (defun get-make-instance-function (key)
345 (let* ((class (car key))
347 (unless (eq *boot-state* 'complete)
348 (return-from get-make-instance-function nil))
349 (when (symbolp class)
350 (setq class (find-class class)))
352 (unless (class-finalized-p class) (finalize-inheritance class)))
353 (let* ((initargs (mapcan #'(lambda (key) (list key nil)) keys))
354 (class-and-initargs (list* class initargs))
355 (make-instance (gdefinition 'make-instance))
356 (make-instance-methods
357 (compute-applicable-methods make-instance class-and-initargs))
358 (std-mi-meth (find-standard-ii-method make-instance-methods 'class))
359 (class+initargs (list class initargs))
360 (default-initargs (gdefinition 'default-initargs))
361 (default-initargs-methods
362 (compute-applicable-methods default-initargs class+initargs))
363 (proto (and (classp class) (class-prototype class)))
364 (initialize-instance-methods
366 (compute-applicable-methods (gdefinition 'initialize-instance)
367 (list* proto initargs))))
368 (shared-initialize-methods
370 (compute-applicable-methods (gdefinition 'shared-initialize)
371 (list* proto t initargs)))))
372 (when (null make-instance-methods)
373 (return-from get-make-instance-function
374 #'(lambda (class initargs)
375 (apply #'no-applicable-method make-instance class initargs))))
376 (unless (and (null (cdr make-instance-methods))
377 (eq (car make-instance-methods) std-mi-meth)
378 (null (cdr default-initargs-methods))
379 (eq (car (method-specializers
380 (car default-initargs-methods)))
381 *the-class-slot-class*)
382 (flet ((check-meth (meth)
383 (let ((quals (method-qualifiers meth)))
385 (eq (car (method-specializers meth))
386 *the-class-slot-object*)
387 (and (null (cdr quals))
388 (or (eq (car quals) ':before)
389 (eq (car quals) ':after)))))))
390 (and (every #'check-meth initialize-instance-methods)
391 (every #'check-meth shared-initialize-methods))))
392 (return-from get-make-instance-function nil))
393 (get-make-instance-function-internal
394 class key (default-initargs class initargs)
395 initialize-instance-methods shared-initialize-methods))))
397 (defun get-make-instance-function-internal (class key initargs
398 initialize-instance-methods
399 shared-initialize-methods)
400 (let* ((keys (cadr key))
401 (allow-other-keys-p (caddr key))
402 (allocate-instance-methods
403 (compute-applicable-methods (gdefinition 'allocate-instance)
404 (list* class initargs))))
405 (unless allow-other-keys-p
406 (unless (check-initargs-1
408 (append allocate-instance-methods
409 initialize-instance-methods
410 shared-initialize-methods)
412 (return-from get-make-instance-function-internal nil)))
413 (if (or (cdr allocate-instance-methods)
414 (some #'complicated-instance-creation-method
415 initialize-instance-methods)
416 (some #'complicated-instance-creation-method
417 shared-initialize-methods))
418 (make-instance-function-complex
420 initialize-instance-methods shared-initialize-methods)
421 (make-instance-function-simple
423 initialize-instance-methods shared-initialize-methods))))
425 (defun complicated-instance-creation-method (m)
426 (let ((qual (method-qualifiers m)))
428 (not (and (null (cdr qual)) (eq (car qual) ':after)))
429 (let ((specl (car (method-specializers m))))
430 (or (not (classp specl))
431 (not (eq 'slot-object (class-name specl))))))))
433 (defun find-standard-ii-method (methods class-names)
435 (when (null (method-qualifiers m))
436 (let ((specl (car (method-specializers m))))
437 (when (and (classp specl)
438 (if (listp class-names)
439 (member (class-name specl) class-names)
440 (eq (class-name specl) class-names)))
443 (defmacro call-initialize-function (initialize-function instance initargs)
444 `(let ((.function. ,initialize-function))
445 (if (and (consp .function.)
446 (eq (car .function.) 'call-initialize-instance-simple))
447 (initialize-instance-simple (cadr .function.) (caddr .function.)
449 (funcall (the function .function.) ,instance ,initargs))))
451 (defun make-instance-function-simple (key class keys
452 initialize-instance-methods
453 shared-initialize-methods)
454 (multiple-value-bind (initialize-function constants)
455 (get-simple-initialization-function class keys (caddr key))
456 (let* ((wrapper (class-wrapper class))
457 (lwrapper (list wrapper))
459 (cond ((structure-class-p class)
460 #'allocate-structure-instance)
461 ((standard-class-p class)
462 #'allocate-standard-instance)
463 ((funcallable-standard-class-p class)
464 #'allocate-funcallable-instance)
466 (error "error in make-instance-function-simple"))))
467 (std-si-meth (find-standard-ii-method shared-initialize-methods
470 (nreverse (mapcar #'(lambda (method)
471 (make-effective-method-function
473 `(call-method ,method nil)
475 (remove std-si-meth shared-initialize-methods))))
476 (std-ii-meth (find-standard-ii-method initialize-instance-methods
479 (nreverse (mapcar #'(lambda (method)
480 (make-effective-method-function
481 #'initialize-instance
482 `(call-method ,method nil)
485 initialize-instance-methods)))))
486 #'(lambda (class1 initargs)
487 (if (not (eq wrapper (class-wrapper class)))
488 (let* ((info (initialize-info class1 initargs))
489 (fn (initialize-info-make-instance-function info)))
490 (declare (type function fn))
491 (funcall fn class1 initargs))
492 (let* ((instance (funcall allocate-function wrapper constants))
493 (initargs (call-initialize-function initialize-function
495 (dolist (fn shared-initfns)
496 (invoke-effective-method-function fn t instance t initargs))
497 (dolist (fn initialize-initfns)
498 (invoke-effective-method-function fn t instance initargs))
501 (defun make-instance-function-complex (key class keys
502 initialize-instance-methods
503 shared-initialize-methods)
504 (multiple-value-bind (initargs-function initialize-function)
505 (get-complex-initialization-functions class keys (caddr key))
506 (let* ((wrapper (class-wrapper class))
508 (get-secondary-dispatch-function
509 #'shared-initialize shared-initialize-methods
510 `((class-eq ,class) t t)
511 `((,(find-standard-ii-method shared-initialize-methods
513 ,#'(lambda (instance init-type &rest initargs)
514 (declare (ignore init-type))
515 (call-initialize-function initialize-function
518 (list wrapper *the-wrapper-of-t* *the-wrapper-of-t*)))
520 (get-secondary-dispatch-function
521 #'initialize-instance initialize-instance-methods
522 `((class-eq ,class) t)
523 `((,(find-standard-ii-method initialize-instance-methods
525 ,#'(lambda (instance &rest initargs)
526 (invoke-effective-method-function
527 shared-initialize t instance t initargs))))
528 (list wrapper *the-wrapper-of-t*))))
529 #'(lambda (class1 initargs)
530 (if (not (eq wrapper (class-wrapper class)))
531 (let* ((info (initialize-info class1 initargs))
532 (fn (initialize-info-make-instance-function info)))
533 (declare (type function fn))
534 (funcall fn class1 initargs))
535 (let* ((initargs (call-initialize-function initargs-function
537 (instance (apply #'allocate-instance class initargs)))
538 (invoke-effective-method-function
539 initialize-instance t instance initargs)
542 (defun get-simple-initialization-function (class
544 &optional allow-other-keys-arg)
545 (let ((info (initialize-info class keys nil allow-other-keys-arg)))
546 (values (initialize-info-combined-initialize-function info)
547 (initialize-info-constants info))))
549 (defun get-complex-initialization-functions (class
554 (let* ((info (initialize-info class keys nil allow-other-keys-arg))
555 (default-initargs-function (initialize-info-default-initargs-function
558 (values default-initargs-function
559 (initialize-info-shared-initialize-t-function info))
560 (values default-initargs-function
561 (initialize-info-shared-initialize-t-function
562 (initialize-info class (initialize-info-new-keys info)
563 nil allow-other-keys-arg))))))
565 (defun add-forms (forms forms-list)
567 (setq forms (copy-list forms))
568 (if (null (car forms-list))
569 (setf (car forms-list) forms)
570 (setf (cddr forms-list) forms))
571 (setf (cdr forms-list) (last forms)))
574 (defun make-default-initargs-form-list (class keys &optional (separate-p t))
575 (let ((initargs-form-list (cons nil nil))
576 (default-initargs (class-default-initargs class))
579 (mapcan #'(lambda (slot)
580 (mapcar #'(lambda (arg)
582 (slot-definition-initargs slot)))
583 (class-slots class)))
586 (pushnew (cdr (assoc key slots-alist)) nslots))
587 (dolist (default default-initargs)
588 (let* ((key (car default))
589 (slot (cdr (assoc key slots-alist)))
590 (function (cadr default)))
591 (unless (member slot nslots)
592 (add-forms `((funcall ,function) (push-initarg ,key))
595 (push slot nslots))))
597 (add-forms `((update-initialize-info-cache
598 ,class ,(initialize-info class nkeys nil)))
600 (add-forms `((finish-pushing-initargs))
602 (values (car initargs-form-list) nkeys)))
604 (defun make-shared-initialize-form-list (class keys si-slot-names simple-p)
605 (let* ((initialize-form-list (cons nil nil))
606 (type (cond ((structure-class-p class)
608 ((standard-class-p class)
610 ((funcallable-standard-class-p class)
612 (t (error "error in make-shared-initialize-form-list"))))
613 (wrapper (class-wrapper class))
614 (constants (when simple-p
615 (make-list (wrapper-no-of-instance-slots wrapper)
616 ':initial-element +slot-unbound+)))
617 (slots (class-slots class))
618 (slot-names (mapcar #'slot-definition-name slots))
619 (slots-key (mapcar #'(lambda (slot)
620 (let ((index most-positive-fixnum))
621 (dolist (key (slot-definition-initargs slot))
622 (let ((pos (position key keys)))
623 (when pos (setq index (min index pos)))))
626 (slots (stable-sort slots-key #'< :key #'cdr)))
628 (dolist (slot+index slots)
629 (let* ((slot (car slot+index))
630 (name (slot-definition-name slot))
631 (npop (1+ (- (cdr slot+index) n-popped))))
632 (unless (eql (cdr slot+index) most-positive-fixnum)
633 (let* ((pv-offset (1+ (position name slot-names))))
634 (add-forms `(,@(when (plusp npop)
635 `((pop-initargs ,(* 2 npop))))
636 (instance-set ,pv-offset ,slot))
637 initialize-form-list))
638 (incf n-popped npop)))))
639 (dolist (slot+index slots)
640 (let* ((slot (car slot+index))
641 (name (slot-definition-name slot)))
642 (when (and (eql (cdr slot+index) most-positive-fixnum)
643 (or (eq si-slot-names t)
644 (member name si-slot-names)))
645 (let* ((initform (slot-definition-initform slot))
646 (initfunction (slot-definition-initfunction slot))
647 (location (unless (eq type 'structure)
648 (slot-definition-location slot)))
649 (pv-offset (1+ (position name slot-names)))
650 (forms (cond ((null initfunction)
652 ((constantp initform)
653 (let ((value (funcall initfunction)))
654 (if (and simple-p (integerp location))
655 (progn (setf (nth location constants)
659 (instance-set ,pv-offset ,slot)))))
661 `((funcall ,(slot-definition-initfunction slot))
662 (instance-set ,pv-offset ,slot))))))
663 (add-forms `(,@(unless (or simple-p (null forms))
664 `((skip-when-instance-boundp ,pv-offset ,slot
667 initialize-form-list)))))
668 (values (car initialize-form-list) constants)))
670 (defvar *class-pv-table-table* (make-hash-table :test 'eq))
672 (defun get-pv-cell-for-class (class)
673 (let* ((slot-names (mapcar #'slot-definition-name (class-slots class)))
674 (slot-name-lists (list (cons nil slot-names)))
675 (pv-table (gethash class *class-pv-table-table*)))
676 (unless (and pv-table
677 (equal slot-name-lists (pv-table-slot-name-lists pv-table)))
678 (setq pv-table (intern-pv-table :slot-name-lists slot-name-lists))
679 (setf (gethash class *class-pv-table-table*) pv-table))
680 (pv-table-lookup pv-table (class-wrapper class))))
682 (defvar *initialize-instance-simple-alist* nil)
683 (defvar *note-iis-entry-p* nil)
685 (defvar *compiled-initialize-instance-simple-functions*
686 (make-hash-table :test 'equal))
688 (defun initialize-instance-simple-function (use info class form-list)
689 (let* ((pv-cell (get-pv-cell-for-class class))
690 (key (initialize-info-key info))
691 (sf-key (list* use (class-name (car key)) (cdr key))))
692 (if (or *compile-make-instance-functions-p*
693 (gethash sf-key *compiled-initialize-instance-simple-functions*))
694 (multiple-value-bind (form args)
695 (form-list-to-lisp pv-cell form-list)
696 (let ((entry (assoc form *initialize-instance-simple-alist*
698 (setf (gethash sf-key
699 *compiled-initialize-instance-simple-functions*)
702 (setf (cdddr entry) (union (list sf-key) (cdddr entry)
705 (setq entry (list* form nil nil (list sf-key)))
706 (setq *initialize-instance-simple-alist*
707 (nconc *initialize-instance-simple-alist*
709 (unless (or *note-iis-entry-p* (cadr entry))
710 (setf (cadr entry) (compile nil (car entry))))
712 (apply (the function (cadr entry)) args)
713 `(call-initialize-instance-simple ,pv-cell ,form-list))))
715 #'(lambda (instance initargs)
716 (initialize-instance-simple pv-cell form-list instance initargs))
718 `(call-initialize-instance-simple ,pv-cell ,form-list))))
720 (defun load-precompiled-iis-entry (form function system uses)
721 (let ((entry (assoc form *initialize-instance-simple-alist*
724 (setq entry (list* form nil nil nil))
725 (setq *initialize-instance-simple-alist*
726 (nconc *initialize-instance-simple-alist*
728 (setf (cadr entry) function)
729 (setf (caddr entry) system)
731 (setf (gethash use *compiled-initialize-instance-simple-functions*) t))
732 (setf (cdddr entry) (union uses (cdddr entry)
735 (defmacro precompile-iis-functions (&optional system)
737 ,@(gathering1 (collecting)
738 (dolist (iis-entry *initialize-instance-simple-alist*)
739 (when (or (null (caddr iis-entry))
740 (eq (caddr iis-entry) system))
741 (when system (setf (caddr iis-entry) system))
743 `(load-precompiled-iis-entry
747 ',(cdddr iis-entry))))))))
749 (defun compile-iis-functions (after-p)
750 (let ((*compile-make-instance-functions-p* t)
751 (*revert-initialize-info-p* t)
752 (*note-iis-entry-p* (not after-p)))
753 (declare (special *compile-make-instance-functions-p*))
754 (when (eq *boot-state* 'complete)
755 (update-make-instance-function-table))))
759 ;(push-initarg const)
760 ;(pop-supplied count) ; a positive odd number
761 ;(instance-set pv-offset slotd)
762 ;(skip-when-instance-boundp pv-offset slotd n)
764 (defun initialize-instance-simple (pv-cell form-list instance initargs)
765 (let ((pv (car pv-cell))
766 (initargs-tail initargs)
767 (slots (get-slots-or-nil instance))
768 (class (class-of instance))
770 (loop (when (null form-list) (return nil))
771 (let ((form (pop form-list)))
774 (push value initargs)
775 (push (cadr form) initargs))
777 (setq value (cadr form)))
779 (setq value (funcall (the function (cadr form)))))
781 (setq initargs-tail (nthcdr (1- (cadr form)) initargs-tail))
782 (setq value (pop initargs-tail)))
784 (instance-write-internal
785 pv slots (cadr form) value
786 (setf (slot-value-using-class class instance (caddr form))
788 (skip-when-instance-boundp
789 (when (instance-boundp-internal
791 (slot-boundp-using-class class instance (caddr form)))
792 (dotimes-fixnum (i (cadddr form))
794 (update-initialize-info-cache
795 (when (consp initargs)
796 (setq initargs (cons (car initargs) (cdr initargs))))
797 (setq *initialize-info-cache-class* (cadr form))
798 (setq *initialize-info-cache-initargs* initargs)
799 (setq *initialize-info-cache-info* (caddr form)))
800 (finish-pushing-initargs
801 (setq initargs-tail initargs)))))
804 (defun add-to-cvector (cvector constant)
805 (or (position constant cvector)
806 (prog1 (fill-pointer cvector)
807 (vector-push-extend constant cvector))))
809 (defvar *inline-iis-instance-locations-p* t)
811 (defun first-form-to-lisp (forms cvector pv)
812 (flet ((const (constant)
813 (cond ((or (numberp constant) (characterp constant))
815 ((and (symbolp constant) (symbol-package constant))
818 `(svref cvector ,(add-to-cvector cvector constant))))))
819 (let ((form (pop (car forms))))
822 `((push value initargs)
823 (push ,(const (cadr form)) initargs)))
825 `((setq value ,(const (cadr form)))))
827 `((setq value (funcall (the function ,(const (cadr form)))))))
829 `((setq initargs-tail (,@(let ((pop (1- (cadr form))))
835 (setq value (pop initargs-tail))))
837 (let* ((pv-offset (cadr form))
838 (location (pvref pv pv-offset))
839 (default `(setf (slot-value-using-class class instance
840 ,(const (caddr form)))
842 (if *inline-iis-instance-locations-p*
845 (setf (clos-slots-ref slots ,(const location))
847 (cons `((setf (cdr ,(const location)) value)))
849 `((instance-write-internal pv slots ,(const pv-offset) value
855 (skip-when-instance-boundp
856 (let* ((pv-offset (cadr form))
857 (location (pvref pv pv-offset))
858 (default `(slot-boundp-using-class class instance
859 ,(const (caddr form)))))
860 `((unless ,(if *inline-iis-instance-locations-p*
862 (fixnum `(not (and slots
867 (cons `(not (eq (cdr ,(const location))
870 `(instance-boundp-internal
871 pv slots ,(const pv-offset)
873 ,(typecase (pvref pv pv-offset)
877 ,@(let ((sforms (cons nil nil)))
878 (dotimes-fixnum (i (cadddr form) (car sforms))
879 (add-forms (first-form-to-lisp forms cvector pv)
881 (update-initialize-info-cache
882 `((when (consp initargs)
883 (setq initargs (cons (car initargs) (cdr initargs))))
884 (setq *initialize-info-cache-class* ,(const (cadr form)))
885 (setq *initialize-info-cache-initargs* initargs)
886 (setq *initialize-info-cache-info* ,(const (caddr form)))))
887 (finish-pushing-initargs
888 `((setq initargs-tail initargs)))))))
890 (defmacro iis-body (&body forms)
891 `(let ((initargs-tail initargs)
892 (slots (get-slots-or-nil instance))
893 (class (class-of instance))
896 initargs instance initargs-tail pv cvector slots class value
899 (defun form-list-to-lisp (pv-cell form-list)
900 (let* ((forms (list form-list))
901 (cvector (make-array (floor (length form-list) 2)
902 :fill-pointer 0 :adjustable t))
904 (body (let ((rforms (cons nil nil)))
905 (loop (when (null (car forms)) (return (car rforms)))
906 (add-forms (first-form-to-lisp forms cvector pv)
908 (cvector-type `(simple-vector ,(length cvector))))
910 `(lambda (pv-cell cvector)
911 (declare (type ,cvector-type cvector))
912 #'(lambda (instance initargs)
913 (declare #.*optimize-speed*)
916 (list pv-cell (coerce cvector cvector-type)))))
918 ;;; The effect of this is to cause almost all of the overhead of
919 ;;; MAKE-INSTANCE to happen at load time (or maybe at precompile time,
920 ;;; as explained in a previous message) rather than the first time
921 ;;; that MAKE-INSTANCE is called with a given class-name and sequence
924 ;;; This optimization applies only when the first argument and all the
925 ;;; even numbered arguments are constants evaluating to interned
928 (declaim (ftype (function (t) symbol) get-make-instance-function-symbol))
930 (define-compiler-macro make-instance (&whole form &rest args)
931 (declare (ignore args))
932 (let* ((*make-instance-function-keys* nil)
933 (expanded-form (expand-make-instance-form form)))
935 `(funcall (fdefinition
936 ;; The name is guaranteed to be fbound.
937 ;; Is there a way to declare this?
939 (get-make-instance-function-symbol
940 ',(first *make-instance-function-keys*))))
941 ,@(cdr expanded-form))
944 (defun get-make-instance-function-symbol (key)
945 (get-make-instance-functions (list key))
946 (make-instance-function-symbol key))