faster SLOT-VALUE &co with variable slot names
[sbcl.git] / src / pcl / wrapper.lisp
index 909eee8..ae181da 100644 (file)
 
     ;; FIXME: We are here inside PCL lock, but might someone be
     ;; accessing the wrapper at the same time from outside the lock?
-    ;; Can it matter that they get 0 from one slot and a valid value
-    ;; from another?
-    (dotimes (i layout-clos-hash-length)
-      (setf (layout-clos-hash owrapper i) 0))
+    (setf (layout-clos-hash owrapper) 0)
 
     ;; FIXME: We could save a whopping cons by using (STATE . WRAPPER)
     ;; instead
   (let* ((owrapper (wrapper-of instance))
          (state (layout-invalid owrapper)))
     (aver (not (eq state :uninitialized)))
-    (etypecase state
-      (null owrapper)
-      ;; FIXME: I can't help thinking that, while this does cure the
-      ;; symptoms observed from some class redefinitions, this isn't
-      ;; the place to be doing this flushing.  Nevertheless...  --
-      ;; CSR, 2003-05-31
-      ;;
-      ;; CMUCL comment:
-      ;;    We assume in this case, that the :INVALID is from a
-      ;;    previous call to REGISTER-LAYOUT for a superclass of
-      ;;    INSTANCE's class.  See also the comment above
-      ;;    FORCE-CACHE-FLUSHES.  Paul Dietz has test cases for this.
-      ((member t)
-       (force-cache-flushes (class-of instance))
-       (check-wrapper-validity instance))
-      (cons
-       (ecase (car state)
-         (:flush
-          (flush-cache-trap owrapper (cadr state) instance))
-         (:obsolete
-          (obsolete-instance-trap owrapper (cadr state) instance)))))))
+    (cond ((not state)
+           owrapper)
+          ((not (layout-for-std-class-p owrapper))
+           ;; Obsolete structure trap.
+           (obsolete-instance-trap owrapper nil instance))
+          ((eq t state)
+           ;; FIXME: I can't help thinking that, while this does cure
+           ;; the symptoms observed from some class redefinitions,
+           ;; this isn't the place to be doing this flushing.
+           ;; Nevertheless... -- CSR, 2003-05-31
+           ;;
+           ;; CMUCL comment:
+           ;;    We assume in this case, that the :INVALID is from a
+           ;;    previous call to REGISTER-LAYOUT for a superclass of
+           ;;    INSTANCE's class.  See also the comment above
+           ;;    FORCE-CACHE-FLUSHES.  Paul Dietz has test cases for this.
+           (force-cache-flushes (class-of instance))
+           (check-wrapper-validity instance))
+          ((consp state)
+           (ecase (car state)
+             (:flush
+              (flush-cache-trap owrapper (cadr state) instance))
+             (:obsolete
+              (obsolete-instance-trap owrapper (cadr state) instance))))
+          (t
+           (bug "Invalid LAYOUT-INVALID: ~S" state)))))
 
 (declaim (inline check-obsolete-instance))
 (defun check-obsolete-instance (instance)
   (when (invalid-wrapper-p (layout-of instance))
     (check-wrapper-validity instance)))
+
+(defun check-obsolete-instance/class-of (instance)
+  (let ((wrapper (wrapper-of instance)))
+    (when (invalid-wrapper-p wrapper)
+      (check-wrapper-validity instance))
+    (wrapper-class* wrapper)))
 \f
 ;;;  NIL: means nothing so far, no actual arg info has NILs in the
-;;;  metatype
+;;;  metatype.
 ;;;
 ;;;  CLASS: seen all sorts of metaclasses (specifically, more than one
 ;;;  of the next 5 values) or else have seen something which doesn't
-;;;  fall into a single category (SLOT-INSTANCE, FORWARD).
+;;;  fall into a single category (SLOT-INSTANCE, FORWARD).  Also used
+;;;  when seen a non-standard specializer.
+;;;
+;;;  T: means everything so far is the class T.
+;;;
+;;;  The above three are the really important ones, as they affect how
+;;;  discriminating functions are computed.  There are some other
+;;;  possible metatypes:
+;;;
+;;;  * STANDARD-INSTANCE: seen only standard classes
+;;;  * BUILT-IN-INSTANCE: seen only built in classes
+;;;  * STRUCTURE-INSTANCE: seen only structure classes
+;;;  * CONDITION-INSTANCE: seen only condition classes
 ;;;
-;;;  T: means everything so far is the class T
-;;;  STANDARD-INSTANCE: seen only standard classes
-;;;  BUILT-IN-INSTANCE: seen only built in classes
-;;;  STRUCTURE-INSTANCE: seen only structure classes
-;;;  CONDITION-INSTANCE: seen only condition classes
+;;;  but these are largely unexploited as of 2007-05-10.  The
+;;;  distinction between STANDARD-INSTANCE and the others is used in
+;;;  emitting wrapper/slot-getting code in accessor discriminating
+;;;  functions (see EMIT-FETCH-WRAPPER and EMIT-READER/WRITER); it is
+;;;  possible that there was an intention to use these metatypes to
+;;;  specialize cache implementation or discrimination nets, but this
+;;;  has not occurred as yet.
 (defun raise-metatype (metatype new-specializer)
   (let ((slot      (find-class 'slot-class))
         (standard  (find-class 'standard-class))
         (built-in  (find-class 'built-in-class))
         (frc       (find-class 'forward-referenced-class)))
     (flet ((specializer->metatype (x)
-             (let ((meta-specializer
-                     (if (eq *boot-state* 'complete)
-                         (class-of (specializer-class x))
-                         (class-of x))))
+             (let* ((specializer-class (if (eq *boot-state* 'complete)
+                                           (specializer-class-or-nil x)
+                                           x))
+                   (meta-specializer (class-of specializer-class)))
                (cond
                  ((eq x *the-class-t*) t)
+                 ((not specializer-class) 'non-standard)
                  ((*subtypep meta-specializer standard) 'standard-instance)
                  ((*subtypep meta-specializer fsc) 'standard-instance)
                  ((*subtypep meta-specializer condition) 'condition-instance)
       (let ((new-metatype (specializer->metatype new-specializer)))
         (cond ((eq new-metatype 'slot-instance) 'class)
               ((eq new-metatype 'forward) 'class)
+              ((eq new-metatype 'non-standard) 'class)
               ((null metatype) new-metatype)
               ((eq metatype new-metatype) new-metatype)
               (t 'class))))))