X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Ftarget-defstruct.lisp;h=0e5742f9f7884f05932f051300a86e4adf9b4650;hb=4ba392170e98744f0ef0b8e08a5d42b988f1d0c9;hp=ef0761face226e618efccabb8f2e124a4e80eced;hpb=ea3a2433c72ee97c5691c29d882a63e4d86f0a32;p=sbcl.git diff --git a/src/code/target-defstruct.lisp b/src/code/target-defstruct.lisp index ef0761f..0e5742f 100644 --- a/src/code/target-defstruct.lisp +++ b/src/code/target-defstruct.lisp @@ -31,112 +31,68 @@ (defun %instance-set (instance index new-value) (setf (%instance-ref instance index) new-value)) -(defun %instance-compare-and-swap (instance index old new) - #!+(or x86 x86-64) - (%instance-compare-and-swap instance index old new) - #!-(or x86 x86-64) - (let ((n-old (%instance-ref instance index))) - (when (eq old n-old) - (%instance-set instance index new)) - n-old)) - -#!-hppa -(progn - (defun %raw-instance-ref/word (instance index) - (declare (type index index)) - (%raw-instance-ref/word instance index)) - (defun %raw-instance-set/word (instance index new-value) - (declare (type index index) - (type sb!vm:word new-value)) - (%raw-instance-set/word instance index new-value)) - - (defun %raw-instance-ref/single (instance index) - (declare (type index index)) - (%raw-instance-ref/single instance index)) - (defun %raw-instance-set/single (instance index new-value) - (declare (type index index) - (type single-float new-value)) - (%raw-instance-set/single instance index new-value)) - - (defun %raw-instance-ref/double (instance index) - (declare (type index index)) - (%raw-instance-ref/double instance index)) - (defun %raw-instance-set/double (instance index new-value) - (declare (type index index) - (type double-float new-value)) - (%raw-instance-set/double instance index new-value)) - - (defun %raw-instance-ref/complex-single (instance index) - (declare (type index index)) - (%raw-instance-ref/complex-single instance index)) - (defun %raw-instance-set/complex-single (instance index new-value) - (declare (type index index) - (type (complex single-float) new-value)) - (%raw-instance-set/complex-single instance index new-value)) - - (defun %raw-instance-ref/complex-double (instance index) - (declare (type index index)) - (%raw-instance-ref/complex-double instance index)) - (defun %raw-instance-set/complex-double (instance index new-value) - (declare (type index index) - (type (complex double-float) new-value)) - (%raw-instance-set/complex-double instance index new-value)) -) ; #!-HPPA - -#!+hppa -(progn -(defun %raw-ref-single (vec index) +;;; Normally IR2 converted, definition needed for interpreted structure +;;; constructors only. +#!+sb-eval +(defun %make-structure-instance (dd slot-specs &rest slot-values) + (let ((instance (%make-instance (dd-instance-length dd)))) + (setf (%instance-layout instance) (dd-layout-or-lose dd)) + (mapc (lambda (spec value) + (destructuring-bind (raw-type . index) (cdr spec) + (macrolet ((make-case () + `(ecase raw-type + ((t) + (setf (%instance-ref instance index) value)) + ,@(mapcar + (lambda (rsd) + `(,(raw-slot-data-raw-type rsd) + (setf (,(raw-slot-data-accessor-name rsd) + instance index) + value))) + *raw-slot-data-list*)))) + (make-case)))) + slot-specs slot-values) + instance)) + +(defun %raw-instance-ref/word (instance index) (declare (type index index)) - (%raw-ref-single vec index)) + (%raw-instance-ref/word instance index)) +(defun %raw-instance-set/word (instance index new-value) + (declare (type index index) + (type sb!vm:word new-value)) + (%raw-instance-set/word instance index new-value)) -(defun %raw-ref-double (vec index) +(defun %raw-instance-ref/single (instance index) (declare (type index index)) - (%raw-ref-double vec index)) + (%raw-instance-ref/single instance index)) +(defun %raw-instance-set/single (instance index new-value) + (declare (type index index) + (type single-float new-value)) + (%raw-instance-set/single instance index new-value)) -#!+long-float -(defun %raw-ref-long (vec index) +(defun %raw-instance-ref/double (instance index) (declare (type index index)) - (%raw-ref-long vec index)) + (%raw-instance-ref/double instance index)) +(defun %raw-instance-set/double (instance index new-value) + (declare (type index index) + (type double-float new-value)) + (%raw-instance-set/double instance index new-value)) -(defun %raw-set-single (vec index val) +(defun %raw-instance-ref/complex-single (instance index) (declare (type index index)) - (%raw-set-single vec index val)) + (%raw-instance-ref/complex-single instance index)) +(defun %raw-instance-set/complex-single (instance index new-value) + (declare (type index index) + (type (complex single-float) new-value)) + (%raw-instance-set/complex-single instance index new-value)) -(defun %raw-set-double (vec index val) +(defun %raw-instance-ref/complex-double (instance index) (declare (type index index)) - (%raw-set-double vec index val)) - -#!+long-float -(defun %raw-set-long (vec index val) - (declare (type index index)) - (%raw-set-long vec index val)) - -(defun %raw-ref-complex-single (vec index) - (declare (type index index)) - (%raw-ref-complex-single vec index)) - -(defun %raw-ref-complex-double (vec index) - (declare (type index index)) - (%raw-ref-complex-double vec index)) - -#!+long-float -(defun %raw-ref-complex-long (vec index) - (declare (type index index)) - (%raw-ref-complex-long vec index)) - -(defun %raw-set-complex-single (vec index val) - (declare (type index index)) - (%raw-set-complex-single vec index val)) - -(defun %raw-set-complex-double (vec index val) - (declare (type index index)) - (%raw-set-complex-double vec index val)) - -#!+long-float -(defun %raw-set-complex-long (vec index val) - (declare (type index index)) - (%raw-set-complex-long vec index val)) -) ; #!+HPPA + (%raw-instance-ref/complex-double instance index)) +(defun %raw-instance-set/complex-double (instance index new-value) + (declare (type index index) + (type (complex double-float) new-value)) + (%raw-instance-set/complex-double instance index new-value)) (defun %instance-layout (instance) (%instance-layout instance)) @@ -147,7 +103,11 @@ (defun %make-funcallable-instance (len) (%make-funcallable-instance len)) -(defun funcallable-instance-p (x) (funcallable-instance-p x)) +(defun funcallable-instance-p (x) + (funcallable-instance-p x)) + +(deftype funcallable-instance () + `(satisfies funcallable-instance-p)) (defun %funcallable-instance-info (fin i) (%funcallable-instance-info fin i)) @@ -160,19 +120,6 @@ (defun (setf funcallable-instance-fun) (new-value fin) (setf (%funcallable-instance-function fin) new-value)) - -;;; service function for structure constructors -(defun %make-instance-with-layout (layout) - ;; Make sure the object ends at a two-word boundary. Note that this does - ;; not affect the amount of memory used, since the allocator would add the - ;; same padding anyway. However, raw slots are indexed from the length of - ;; the object as indicated in the header, so the pad word needs to be - ;; included in that length to guarantee proper alignment of raw double float - ;; slots, necessary for (at least) the SPARC backend. - (let* ((length (layout-length layout)) - (result (%make-instance (+ length (mod (1+ length) 2))))) - (setf (%instance-layout result) layout) - result)) ;;;; target-only parts of the DEFSTRUCT top level code @@ -192,6 +139,36 @@ (/show0 "leaving PROTECT-CL") (values)) +(defun make-defstruct-predicate (dd layout) + (ecase (dd-type dd) + ;; structures with LAYOUTs + ((structure funcallable-structure) + (/show0 "with-LAYOUT case") + #'(lambda (object) + (locally ; <- to keep SAFETY 0 from affecting arg count checking + (declare (optimize (speed 3) (safety 0))) + (/noshow0 "in with-LAYOUT structure predicate closure,") + (/noshow0 " OBJECT,LAYOUT=..") + (/nohexstr object) + (/nohexstr layout) + (typep-to-layout object layout)))) + ;; structures with no LAYOUT (i.e. :TYPE VECTOR or :TYPE LIST) + ;; + ;; FIXME: should handle the :NAMED T case in these cases + (vector + (/show0 ":TYPE VECTOR case") + #'vectorp) + (list + (/show0 ":TYPE LIST case") + #'listp))) + +(defun make-defstruct-copier (dd layout) + (ecase (dd-type dd) + (structure + #'(lambda (instance) + (%check-structure-type-from-layout instance layout) + (copy-structure instance))))) + ;;; the part of %DEFSTRUCT which makes sense only on the target SBCL ;;; ;;; (The "static" in the name is because it needs to be done not only @@ -241,34 +218,14 @@ ;; (And funcallable instances don't need copiers anyway.) (aver (eql (dd-type dd) 'structure)) (setf (symbol-function (dd-copier-name dd)) - ;; FIXME: should use a closure which checks arg type before copying - #'copy-structure)) + (make-defstruct-copier dd layout))) ;; Set FDEFINITION for predicate. (when (dd-predicate-name dd) (/show0 "doing FDEFINITION for predicate") (protect-cl (dd-predicate-name dd)) (setf (symbol-function (dd-predicate-name dd)) - (ecase (dd-type dd) - ;; structures with LAYOUTs - ((structure funcallable-structure) - (/show0 "with-LAYOUT case") - (lambda (object) - (locally ; <- to keep SAFETY 0 from affecting arg count checking - (declare (optimize (speed 3) (safety 0))) - (/noshow0 "in with-LAYOUT structure predicate closure, OBJECT,LAYOUT=..") - (/nohexstr object) - (/nohexstr layout) - (typep-to-layout object layout)))) - ;; structures with no LAYOUT (i.e. :TYPE VECTOR or :TYPE LIST) - ;; - ;; FIXME: should handle the :NAMED T case in these cases - (vector - (/show0 ":TYPE VECTOR case") - #'vectorp) - (list - (/show0 ":TYPE LIST case") - #'listp)))) + (make-defstruct-predicate dd layout))) (when (dd-doc dd) (setf (fdocumentation (dd-name dd) 'structure) @@ -404,16 +361,16 @@ #!+sb-doc "Return a copy of STRUCTURE with the same (EQL) slot values." (declare (type structure-object structure)) - (let* ((len (%instance-length structure)) - (res (%make-instance len)) - (layout (%instance-layout structure)) + (let* ((layout (%instance-layout structure)) + (res (%make-instance (%instance-length structure))) + (len (layout-length layout)) (nuntagged (layout-n-untagged-slots layout))) (declare (type index len)) (when (layout-invalid layout) (error "attempt to copy an obsolete structure:~% ~S" structure)) - ;; Copy ordinary slots. + ;; Copy ordinary slots and layout. (dotimes (i (- len nuntagged)) (declare (type index i)) (setf (%instance-ref res i) @@ -426,84 +383,107 @@ (%raw-instance-ref/word structure i))) res)) + + + +;; Do an EQUALP comparison on the raw slots (only, not the normal slots) of a +;; structure. +(defun raw-instance-slots-equalp (layout x y) + ;; This implementation sucks, but hopefully EQUALP on raw structures + ;; won't be a major bottleneck for anyone. It'd be tempting to do + ;; all this with %RAW-INSTANCE-REF/WORD and bitwise comparisons, but + ;; that'll fail in some cases. For example -0.0 and 0.0 are EQUALP + ;; but have different bit patterns. -- JES, 2007-08-21 + (loop for dsd in (dd-slots (layout-info layout)) + for raw-type = (dsd-raw-type dsd) + for rsd = (unless (eql raw-type t) + (find raw-type + *raw-slot-data-list* + :key 'raw-slot-data-raw-type)) + always (or (not rsd) + (funcall (raw-slot-data-comparer rsd) (dsd-index dsd) x y)))) ;;; default PRINT-OBJECT method +(defun %print-structure-sans-layout-info (name stream) + ;; KLUDGE: during PCL build debugging, we can sometimes + ;; attempt to print out a PCL object (with null LAYOUT-INFO). + (pprint-logical-block (stream nil :prefix "#<" :suffix ">") + (prin1 name stream) + (write-char #\space stream) + (write-string "(no LAYOUT-INFO)" stream))) + +(defun %print-structure-sans-slots (name stream) + ;; the structure type doesn't count as a component for *PRINT-LEVEL* + ;; processing. We can likewise elide the logical block processing, + ;; since all we have to print is the type name. -- CSR, 2004-10-05 + (write-string "#S(" stream) + (prin1 name stream) + (write-char #\) stream)) + (defun %default-structure-pretty-print (structure stream) (let* ((layout (%instance-layout structure)) (name (classoid-name (layout-classoid layout))) (dd (layout-info layout))) - ;; KLUDGE: during the build process with SB-SHOW, we can sometimes - ;; attempt to print out a PCL object (with null LAYOUT-INFO). - #!+sb-show - (when (null dd) - (pprint-logical-block (stream nil :prefix "#<" :suffix ">") - (prin1 name stream) - (write-char #\space stream) - (write-string "(no LAYOUT-INFO)")) - (return-from %default-structure-pretty-print nil)) - ;; the structure type doesn't count as a component for - ;; *PRINT-LEVEL* processing. We can likewise elide the logical - ;; block processing, since all we have to print is the type name. - ;; -- CSR, 2004-10-05 - (when (and dd (null (dd-slots dd))) - (write-string "#S(" stream) - (prin1 name stream) - (write-char #\) stream) - (return-from %default-structure-pretty-print nil)) - (pprint-logical-block (stream nil :prefix "#S(" :suffix ")") - (prin1 name stream) - (let ((remaining-slots (dd-slots dd))) - (when remaining-slots - (write-char #\space stream) - ;; CMU CL had (PPRINT-INDENT :BLOCK 2 STREAM) here, - ;; but I can't see why. -- WHN 20000205 - (pprint-newline :linear stream) - (loop - (pprint-pop) - (let ((slot (pop remaining-slots))) - (write-char #\: stream) - (output-symbol-name (symbol-name (dsd-name slot)) stream) - (write-char #\space stream) - (pprint-newline :miser stream) - (output-object (funcall (fdefinition (dsd-accessor-name slot)) - structure) - stream) - (when (null remaining-slots) - (return)) - (write-char #\space stream) - (pprint-newline :linear stream)))))))) + (cond ((not dd) + (%print-structure-sans-layout-info name stream)) + ((not (dd-slots dd)) + (%print-structure-sans-slots name stream)) + (t + (pprint-logical-block (stream nil :prefix "#S(" :suffix ")") + (prin1 name stream) + (let ((remaining-slots (dd-slots dd))) + (when remaining-slots + (write-char #\space stream) + ;; CMU CL had (PPRINT-INDENT :BLOCK 2 STREAM) here, + ;; but I can't see why. -- WHN 20000205 + (pprint-newline :linear stream) + (loop + (pprint-pop) + (let ((slot (pop remaining-slots))) + (write-char #\: stream) + (output-symbol-name (symbol-name (dsd-name slot)) stream) + (write-char #\space stream) + (pprint-newline :miser stream) + (output-object (funcall (fdefinition (dsd-accessor-name slot)) + structure) + stream) + (when (null remaining-slots) + (return)) + (write-char #\space stream) + (pprint-newline :linear stream)))))))))) + (defun %default-structure-ugly-print (structure stream) (let* ((layout (%instance-layout structure)) (name (classoid-name (layout-classoid layout))) (dd (layout-info layout))) - (when (and dd (null (dd-slots dd))) - (write-string "#S(" stream) - (prin1 name stream) - (write-char #\) stream) - (return-from %default-structure-ugly-print nil)) - (descend-into (stream) - (write-string "#S(" stream) - (prin1 name stream) - (do ((index 0 (1+ index)) - (remaining-slots (dd-slots dd) (cdr remaining-slots))) - ((or (null remaining-slots) - (and (not *print-readably*) - *print-length* - (>= index *print-length*))) - (if (null remaining-slots) - (write-string ")" stream) - (write-string " ...)" stream))) - (declare (type index index)) - (write-char #\space stream) - (write-char #\: stream) - (let ((slot (first remaining-slots))) - (output-symbol-name (symbol-name (dsd-name slot)) stream) - (write-char #\space stream) - (output-object - (funcall (fdefinition (dsd-accessor-name slot)) - structure) - stream)))))) + (cond ((not dd) + (%print-structure-sans-layout-info name stream)) + ((not (dd-slots dd)) + (%print-structure-sans-slots name stream)) + (t + (descend-into (stream) + (write-string "#S(" stream) + (prin1 name stream) + (do ((index 0 (1+ index)) + (remaining-slots (dd-slots dd) (cdr remaining-slots))) + ((or (null remaining-slots) + (and (not *print-readably*) + *print-length* + (>= index *print-length*))) + (if (null remaining-slots) + (write-string ")" stream) + (write-string " ...)" stream))) + (declare (type index index)) + (write-string " :" stream) + (let ((slot (first remaining-slots))) + (output-symbol-name (symbol-name (dsd-name slot)) stream) + (write-char #\space stream) + (output-object + (funcall (fdefinition (dsd-accessor-name slot)) + structure) + stream)))))))) + (defun default-structure-print (structure stream depth) (declare (ignore depth)) (cond ((funcallable-instance-p structure) @@ -512,6 +492,7 @@ (%default-structure-pretty-print structure stream)) (t (%default-structure-ugly-print structure stream)))) + (def!method print-object ((x structure-object) stream) (default-structure-print x stream *current-level-in-print*)) @@ -534,28 +515,25 @@ (/nohexstr obj) (/nohexstr layout) (when (layout-invalid layout) - (error "An obsolete structure accessor function was called.")) + (error "An obsolete structure typecheck function was called.")) (/noshow0 "back from testing LAYOUT-INVALID LAYOUT") (and (%instancep obj) (let ((obj-layout (%instance-layout obj))) - (cond ((eq obj-layout layout) - ;; (In this case OBJ-LAYOUT can't be invalid, because - ;; we determined LAYOUT is valid in the test above.) - (/noshow0 "EQ case") - t) - ((layout-invalid obj-layout) - (/noshow0 "LAYOUT-INVALID case") - (error 'layout-invalid - :expected-type (layout-classoid obj-layout) - :datum obj)) - (t - (let ((depthoid (layout-depthoid layout))) - (/noshow0 "DEPTHOID case, DEPTHOID,LAYOUT-INHERITS=..") - (/nohexstr depthoid) - (/nohexstr layout-inherits) - (and (> (layout-depthoid obj-layout) depthoid) - (eq (svref (layout-inherits obj-layout) depthoid) - layout)))))))) + (when (eq obj-layout layout) + ;; (In this case OBJ-LAYOUT can't be invalid, because + ;; we determined LAYOUT is valid in the test above.) + (/noshow0 "EQ case") + (return-from typep-to-layout t)) + (when (layout-invalid obj-layout) + (/noshow0 "LAYOUT-INVALID case") + (setf obj-layout (update-object-layout-or-invalid obj layout))) + (let ((depthoid (layout-depthoid layout))) + (/noshow0 "DEPTHOID case, DEPTHOID,LAYOUT-INHERITS=..") + (/nohexstr depthoid) + (/nohexstr layout-inherits) + (and (> (layout-depthoid obj-layout) depthoid) + (eq (svref (layout-inherits obj-layout) depthoid) + layout)))))) ;;;; checking structure types