X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fpcl%2Finit.lisp;h=5b6d913adda85a230046c0794f360557f4d116da;hb=e57523089c7ad0ce2c874c03ecfe721d299efbfb;hp=6696bbaac304ff422a8f2cf2f5df44fe9f51db46;hpb=29003bacae52b0b32626b30e67d6f82a9f4dbce7;p=sbcl.git diff --git a/src/pcl/init.lisp b/src/pcl/init.lisp index 6696bba..5b6d913 100644 --- a/src/pcl/init.lisp +++ b/src/pcl/init.lisp @@ -29,29 +29,21 @@ (apply #'make-instance (find-class class) initargs)) (defmethod make-instance ((class class) &rest initargs) + (let ((instance-or-nil (maybe-call-ctor class initargs))) + (when instance-or-nil + (return-from make-instance instance-or-nil))) (unless (class-finalized-p class) (finalize-inheritance class)) (let ((class-default-initargs (class-default-initargs class))) (when class-default-initargs - (setf initargs (default-initargs class initargs class-default-initargs))) + (setf initargs (default-initargs initargs class-default-initargs))) (when initargs - (when (and (eq *boot-state* 'complete) - (not (getf initargs :allow-other-keys))) - (let ((class-proto (class-prototype class))) - (check-initargs-1 - class initargs - (append (compute-applicable-methods - #'allocate-instance (list class)) - (compute-applicable-methods - #'initialize-instance (list class-proto)) - (compute-applicable-methods - #'shared-initialize (list class-proto t))))))) + (when (eq **boot-state** 'complete) + (check-mi-initargs class initargs))) (let ((instance (apply #'allocate-instance class initargs))) (apply #'initialize-instance instance initargs) instance))) -(defmethod default-initargs ((class slot-class) - supplied-initargs - class-default-initargs) +(defun default-initargs (supplied-initargs class-default-initargs) (loop for (key nil fun) in class-default-initargs when (eq (getf supplied-initargs key '.not-there.) '.not-there.) append (list key (funcall fun)) into default-initargs @@ -68,6 +60,38 @@ (apply #'shared-initialize instance nil initargs) instance) +(defglobal **typecheck-cache** (make-hash-table :test #'equal)) + +(defun generate-slotd-typecheck (slotd) + (let ((type (slot-definition-type slotd))) + (values + (when (and (neq t type) (safe-p (slot-definition-class slotd))) + (with-locked-system-table (**typecheck-cache**) + (or (gethash type **typecheck-cache**) + (setf (gethash type **typecheck-cache**) + (handler-bind (((or style-warning compiler-note) + #'muffle-warning)) + (funcall (compile + nil + `(lambda () + (declare (optimize (sb-c:store-coverage-data 0) + (sb-c::type-check 3) + (sb-c::verify-arg-count 0))) + (named-lambda (slot-typecheck ,type) (value) + (the ,type value)))))))))) + type))) + +(defmethod initialize-instance :after ((slotd effective-slot-definition) &key) + (setf (slot-definition-info slotd) + (multiple-value-bind (typecheck type) (generate-slotd-typecheck slotd) + (make-slot-info :slotd slotd + :typecheck typecheck)))) + +;;; FIXME: Do we need (SETF SLOT-DEFINITION-TYPE) at all? +(defmethod (setf slot-definition-type) :after (new-type (slotd effective-slot-definition)) + (multiple-value-bind (typecheck type) (generate-slotd-typecheck slotd) + (setf (slot-info-typecheck (slot-definition-info slotd)) typecheck))) + (defmethod update-instance-for-different-class ((previous standard-object) (current standard-object) &rest initargs) ;; First we must compute the newly added slots. The spec defines @@ -101,10 +125,10 @@ (flet ((initialize-slot-from-initarg (class instance slotd) (let ((slot-initargs (slot-definition-initargs slotd))) (doplist (initarg value) initargs - (when (memq initarg slot-initargs) - (setf (slot-value-using-class class instance slotd) - value) - (return t))))) + (when (memq initarg slot-initargs) + (setf (slot-value-using-class class instance slotd) + value) + (return t))))) (initialize-slot-from-initfunction (class instance slotd) ;; CLHS: If a before method stores something in a slot, ;; that slot won't be initialized from its :INITFORM, if any. @@ -127,12 +151,9 @@ unless (initialize-slot-from-initarg class instance slotd) collect slotd))) (dolist (slotd initfn-slotds) - (unless (eq (slot-definition-allocation slotd) :class) - ;; :ALLOCATION :CLASS slots use the :INITFORM when class is defined - ;; or redefined, not when instances are allocated. - (when (or (eq t slot-names) - (memq (slot-definition-name slotd) slot-names)) - (initialize-slot-from-initfunction class instance slotd))))) + (when (or (eq t slot-names) + (memq (slot-definition-name slotd) slot-names)) + (initialize-slot-from-initfunction class instance slotd)))) instance)) ;;; If initargs are valid return nil, otherwise signal an error.