1.0.46.11: faster slot-accesses in the presence of SLOT-VALUE-USING-CLASS &co
[sbcl.git] / src / pcl / init.lisp
index 62a342f..8a7b123 100644 (file)
   (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
   (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-hash-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