;;; know about dumping to a fasl file. (We need to objectify the
;;; state because the fasdumper must be reentrant.)
(defstruct (fasl-output
- #-no-ansi-print-object
- (:print-object (lambda (x s)
- (print-unreadable-object (x s :type t)
- (prin1 (namestring (fasl-output-stream x))
- s))))
- (:copier nil))
+ #-no-ansi-print-object
+ (:print-object (lambda (x s)
+ (print-unreadable-object (x s :type t)
+ (prin1 (namestring (fasl-output-stream x))
+ s))))
+ (:copier nil))
;; the stream we dump to
(stream (missing-arg) :type stream)
;; hashtables we use to keep track of dumped constants so that we
(dotimes (i sb!vm:n-word-bytes)
(write-byte (ldb (byte 8 (* 8 i)) num) stream))))
+;; Dump a 32-bit integer.
+(defun dump-unsigned-byte-32 (num fasl-output)
+ (declare (type sb!vm:word num))
+ (declare (type fasl-output fasl-output))
+ (let ((stream (fasl-output-stream fasl-output)))
+ (dotimes (i 4)
+ (write-byte (ldb (byte 8 (* 8 i)) num) stream))))
+
;;; Dump NUM to the fasl stream, represented by N bytes. This works
;;; for either signed or unsigned integers. There's no range checking
;;; -- if you don't specify enough bytes for the number to fit, this
;;; optimizations should be conditional on #!+SB-FROZEN.
(defmacro dump-fop (fs file)
(let* ((fs (eval fs))
- (val (get fs 'fop-code)))
+ (val (get fs 'fop-code)))
(if val
`(progn
- #!+sb-show
- (when *fop-nop4-count*
- (dump-byte ,(get 'fop-nop4 'fop-code) ,file)
- (dump-integer-as-n-bytes (mod (incf *fop-nop4-count*) (expt 2 32))
+ #!+sb-show
+ (when *fop-nop4-count*
+ (dump-byte ,(get 'fop-nop4 'fop-code) ,file)
+ (dump-integer-as-n-bytes (mod (incf *fop-nop4-count*) (expt 2 32))
4 ,file))
- (dump-byte ',val ,file))
+ (dump-byte ',val ,file))
(error "compiler bug: ~S is not a legal fasload operator." fs))))
;;; Dump a FOP-CODE along with an integer argument, choosing the FOP
;;; compiler-macro expansion.
(defmacro dump-fop* (n byte-fop word-fop file)
(once-only ((n-n n)
- (n-file file))
+ (n-file file))
`(cond ((< ,n-n 256)
- (dump-fop ',byte-fop ,n-file)
- (dump-byte ,n-n ,n-file))
- (t
- (dump-fop ',word-fop ,n-file)
- (dump-word ,n-n ,n-file)))))
+ (dump-fop ',byte-fop ,n-file)
+ (dump-byte ,n-n ,n-file))
+ (t
+ (dump-fop ',word-fop ,n-file)
+ (dump-word ,n-n ,n-file)))))
;;; Push the object at table offset Handle on the fasl stack.
(defun dump-push (handle fasl-output)
(declare (type fasl-output fasl-output))
(unless *cold-load-dump*
(let ((handle (gethash x (fasl-output-equal-table fasl-output))))
- (cond (handle
- (dump-push handle fasl-output)
- t)
- (t
- nil)))))
+ (cond
+ (handle (dump-push handle fasl-output) t)
+ (t nil)))))
+(defun string-check-table (x fasl-output)
+ (declare (type fasl-output fasl-output)
+ (type string x))
+ (unless *cold-load-dump*
+ (let ((handle (cdr (assoc
+ (array-element-type x)
+ (gethash x (fasl-output-equal-table fasl-output))))))
+ (cond
+ (handle (dump-push handle fasl-output) t)
+ (t nil)))))
;;; These functions are called after dumping an object to save the
;;; object in the table. The object (also passed in as X) must already
(setf (gethash x (fasl-output-eq-table fasl-output)) handle)
(dump-push handle fasl-output)))
(values))
-
+(defun string-save-object (x fasl-output)
+ (declare (type fasl-output fasl-output)
+ (type string x))
+ (unless *cold-load-dump*
+ (let ((handle (dump-pop fasl-output)))
+ (push (cons (array-element-type x) handle)
+ (gethash x (fasl-output-equal-table fasl-output)))
+ (setf (gethash x (fasl-output-eq-table fasl-output)) handle)
+ (dump-push handle fasl-output)))
+ (values))
;;; Record X in File's CIRCULARITY-TABLE unless *COLD-LOAD-DUMP* is
;;; true. This is called on objects that we are about to dump might
;;; have a circular path through them.
;;; encodings -- CSR, 2002-04-25
(defun fasl-write-string (string stream)
(loop for char across string
- do (let ((code (char-code char)))
- (aver (<= 0 code 127))
- (write-byte code stream))))
+ do (let ((code (char-code char)))
+ (aver (<= 0 code 127))
+ (write-byte code stream))))
;;; Open a fasl file, write its header, and return a FASL-OUTPUT
;;; object for dumping to it. Some human-readable information about
-;;; the source code is given by the string WHERE. If BYTE-P is true,
-;;; this file will contain no native code, and is thus largely
-;;; implementation independent.
+;;; the source code is given by the string WHERE.
(defun open-fasl-output (name where)
(declare (type pathname name))
(let* ((stream (open name
- :direction :output
- :if-exists :supersede
- :element-type 'sb!assem:assembly-unit))
- (res (make-fasl-output :stream stream)))
+ :direction :output
+ :if-exists :supersede
+ :element-type 'sb!assem:assembly-unit))
+ (res (make-fasl-output :stream stream)))
;; Begin the header with the constant machine-readable (and
;; semi-human-readable) string which is used to identify fasl files.
(fasl-write-string
(with-standard-io-syntax
(let ((*print-readably* nil)
- (*print-pretty* nil))
- (format nil
- "~% ~
+ (*print-pretty* nil))
+ (format nil
+ "~% ~
compiled from ~S~% ~
at ~A~% ~
on ~A~% ~
using ~A version ~A~%"
- where
- (format-universal-time nil (get-universal-time))
- (machine-instance)
- (sb!xc:lisp-implementation-type)
- (sb!xc:lisp-implementation-version))))
+ where
+ (format-universal-time nil (get-universal-time))
+ (machine-instance)
+ (sb!xc:lisp-implementation-type)
+ (sb!xc:lisp-implementation-version))))
stream)
(dump-byte +fasl-header-string-stop-char-code+ res)
;; Finish the header by outputting fasl file implementation,
;; version, and key *FEATURES*.
(flet ((dump-counted-string (string)
- (dump-word (length string) res)
- (dotimes (i (length string))
- (dump-byte (char-code (aref string i)) res))))
+ ;; The count is dumped as a 32-bit unsigned-byte even on 64-bit
+ ;; platforms. This ensures that a x86-64 SBCL can gracefully
+ ;; detect an error when trying to read a x86 fasl, instead
+ ;; of choking on a ridiculously long counted string.
+ ;; -- JES, 2005-12-30
+ (dump-unsigned-byte-32 (length string) res)
+ (dotimes (i (length string))
+ (dump-byte (char-code (aref string i)) res))))
(dump-counted-string (symbol-name +backend-fasl-file-implementation+))
- (dump-word +fasl-file-version+ res)
+ (dump-word +fasl-file-version+ res)
(dump-counted-string *features-affecting-fasl-format*))
res))
-;;; Close the specified FASL-OUTPUT, aborting the write if ABORT-P.
+;;; Close the specified FASL-OUTPUT, aborting the write if ABORT-P.
(defun close-fasl-output (fasl-output abort-p)
(declare (type fasl-output fasl-output))
(dump-fop 'fop-verify-empty-stack fasl-output)
(dump-fop 'fop-verify-table-size fasl-output)
(dump-word (fasl-output-table-free fasl-output)
- fasl-output)
+ fasl-output)
(dump-fop 'fop-end-group fasl-output)
;; That's all, folks.
(defun dump-non-immediate-object (x file)
(let ((index (gethash x (fasl-output-eq-table file))))
(cond ((and index (not *cold-load-dump*))
- (dump-push index file))
- (t
- (typecase x
- (symbol (dump-symbol x file))
- (list
- ;; KLUDGE: The code in this case has been hacked
- ;; to match Douglas Crosher's quick fix to CMU CL
- ;; (on cmucl-imp 1999-12-27), applied in sbcl-0.6.8.11
- ;; with help from Martin Atzmueller. This is not an
- ;; ideal solution; to quote DTC,
- ;; The compiler locks up trying to coalesce the
- ;; constant lists. The hack below will disable the
- ;; coalescing of lists while dumping and allows
+ (dump-push index file))
+ (t
+ (typecase x
+ (symbol (dump-symbol x file))
+ (list
+ ;; KLUDGE: The code in this case has been hacked
+ ;; to match Douglas Crosher's quick fix to CMU CL
+ ;; (on cmucl-imp 1999-12-27), applied in sbcl-0.6.8.11
+ ;; with help from Martin Atzmueller. This is not an
+ ;; ideal solution; to quote DTC,
+ ;; The compiler locks up trying to coalesce the
+ ;; constant lists. The hack below will disable the
+ ;; coalescing of lists while dumping and allows
;; the code to compile. The real fix would be to
- ;; take a little more care while dumping these.
- ;; So if better list coalescing is needed, start here.
- ;; -- WHN 2000-11-07
- (if (cyclic-list-p x)
- (progn
- (dump-list x file)
- (eq-save-object x file))
- (unless (equal-check-table x file)
- (dump-list x file)
- (equal-save-object x file))))
- (layout
- (dump-layout x file)
- (eq-save-object x file))
- (instance
- (dump-structure x file)
- (eq-save-object x file))
- (array
- ;; FIXME: The comment at the head of
- ;; DUMP-NON-IMMEDIATE-OBJECT says it's for objects which
- ;; we want to save, instead of repeatedly dumping them.
- ;; But then we dump arrays here without doing anything
- ;; like EQUAL-SAVE-OBJECT. What gives?
- (dump-array x file))
- (number
- (unless (equal-check-table x file)
- (etypecase x
- (ratio (dump-ratio x file))
- (complex (dump-complex x file))
- (float (dump-float x file))
- (integer (dump-integer x file)))
- (equal-save-object x file)))
- (t
- ;; This probably never happens, since bad things tend to
- ;; be detected during IR1 conversion.
- (error "This object cannot be dumped into a fasl file:~% ~S"
- x))))))
+ ;; take a little more care while dumping these.
+ ;; So if better list coalescing is needed, start here.
+ ;; -- WHN 2000-11-07
+ (if (maybe-cyclic-p x)
+ (progn
+ (dump-list x file)
+ (eq-save-object x file))
+ (unless (equal-check-table x file)
+ (dump-list x file)
+ (equal-save-object x file))))
+ (layout
+ (dump-layout x file)
+ (eq-save-object x file))
+ (instance
+ (dump-structure x file)
+ (eq-save-object x file))
+ (array
+ ;; DUMP-ARRAY (and its callees) are responsible for
+ ;; updating the EQ and EQUAL hash tables.
+ (dump-array x file))
+ (number
+ (unless (equal-check-table x file)
+ (etypecase x
+ (ratio (dump-ratio x file))
+ (complex (dump-complex x file))
+ (float (dump-float x file))
+ (integer (dump-integer x file)))
+ (equal-save-object x file)))
+ (t
+ ;; This probably never happens, since bad things tend to
+ ;; be detected during IR1 conversion.
+ (error "This object cannot be dumped into a fasl file:~% ~S"
+ x))))))
(values))
;;; Dump an object of any type by dispatching to the correct
;;; assumed that there is a top level call to DUMP-OBJECT.
(defun sub-dump-object (x file)
(cond ((listp x)
- (if x
- (dump-non-immediate-object x file)
- (dump-fop 'fop-empty-list file)))
- ((symbolp x)
- (if (eq x t)
- (dump-fop 'fop-truth file)
- (dump-non-immediate-object x file)))
- ((fixnump x) (dump-integer x file))
- ((characterp x) (dump-character x file))
- (t
- (dump-non-immediate-object x file))))
+ (if x
+ (dump-non-immediate-object x file)
+ (dump-fop 'fop-empty-list file)))
+ ((symbolp x)
+ (if (eq x t)
+ (dump-fop 'fop-truth file)
+ (dump-non-immediate-object x file)))
+ ((fixnump x) (dump-integer x file))
+ ((characterp x) (dump-character x file))
+ (t
+ (dump-non-immediate-object x file))))
;;; Dump stuff to backpatch already dumped objects. INFOS is the list
;;; of CIRCULARITY structures describing what to do. The patching FOPs
(dolist (info infos)
(let* ((value (circularity-value info))
- (enclosing (circularity-enclosing-object info)))
- (dump-push (gethash enclosing table) file)
- (unless (eq enclosing value)
- (do ((current enclosing (cdr current))
- (i 0 (1+ i)))
- ((eq current value)
- (dump-fop 'fop-nthcdr file)
- (dump-word i file))
- (declare (type index i)))))
+ (enclosing (circularity-enclosing-object info)))
+ (dump-push (gethash enclosing table) file)
+ (unless (eq enclosing value)
+ (do ((current enclosing (cdr current))
+ (i 0 (1+ i)))
+ ((eq current value)
+ (dump-fop 'fop-nthcdr file)
+ (dump-word i file))
+ (declare (type index i)))))
(ecase (circularity-type info)
(:rplaca (dump-fop 'fop-rplaca file))
(defun dump-object (x file)
(if (compound-object-p x)
(let ((*circularities-detected* ())
- (circ (fasl-output-circularity-table file)))
- (clrhash circ)
- (sub-dump-object x file)
- (when *circularities-detected*
- (dump-circularities *circularities-detected* file)
- (clrhash circ)))
+ (circ (fasl-output-circularity-table file)))
+ (clrhash circ)
+ (sub-dump-object x file)
+ (when *circularities-detected*
+ (dump-circularities *circularities-detected* file)
+ (clrhash circ)))
(sub-dump-object x file)))
\f
;;;; LOAD-TIME-VALUE and MAKE-LOAD-FORM support
(defun fasl-dump-load-time-value-lambda (fun file)
(declare (type sb!c::clambda fun) (type fasl-output file))
(let ((handle (gethash (sb!c::leaf-info fun)
- (fasl-output-entry-table file))))
+ (fasl-output-entry-table file))))
(aver handle)
(dump-push handle file)
(dump-fop 'fop-funcall file)
;;; dumped if it's in the EQ table.
(defun fasl-constant-already-dumped-p (constant file)
(if (or (gethash constant (fasl-output-eq-table file))
- (gethash constant (fasl-output-valid-structures file)))
+ (gethash constant (fasl-output-valid-structures file)))
t
nil))
\f
;;;; number dumping
-;;; Dump a ratio.
(defun dump-ratio (x file)
(sub-dump-object (numerator x) file)
(sub-dump-object (denominator x) file)
(dump-fop 'fop-ratio file))
-;;; Dump an integer.
(defun dump-integer (n file)
(typecase n
((signed-byte 8)
(defun dump-package (pkg file)
(declare (inline assoc))
(cond ((cdr (assoc pkg (fasl-output-packages file) :test #'eq)))
- (t
- (unless *cold-load-dump*
- (dump-fop 'fop-normal-load file))
- (dump-simple-string (package-name pkg) file)
- (dump-fop 'fop-package file)
- (unless *cold-load-dump*
- (dump-fop 'fop-maybe-cold-load file))
- (let ((entry (dump-pop file)))
- (push (cons pkg entry) (fasl-output-packages file))
- entry))))
+ (t
+ (unless *cold-load-dump*
+ (dump-fop 'fop-normal-load file))
+ #+sb-xc-host
+ (dump-simple-base-string
+ (coerce (package-name pkg) 'simple-base-string)
+ file)
+ #-sb-xc-host
+ (#!+sb-unicode dump-simple-character-string
+ #!-sb-unicode dump-simple-base-string
+ (coerce (package-name pkg) '(simple-array character (*)))
+ file)
+ (dump-fop 'fop-package file)
+ (unless *cold-load-dump*
+ (dump-fop 'fop-maybe-cold-load file))
+ (let ((entry (dump-pop file)))
+ (push (cons pkg entry) (fasl-output-packages file))
+ entry))))
\f
;;; dumper for lists
;;; This inhibits all circularity detection.
(defun dump-list (list file)
(aver (and list
- (not (gethash list (fasl-output-circularity-table file)))))
+ (not (gethash list (fasl-output-circularity-table file)))))
(do* ((l list (cdr l))
- (n 0 (1+ n))
- (circ (fasl-output-circularity-table file)))
+ (n 0 (1+ n))
+ (circ (fasl-output-circularity-table file)))
((atom l)
- (cond ((null l)
- (terminate-undotted-list n file))
- (t
- (sub-dump-object l file)
- (terminate-dotted-list n file))))
+ (cond ((null l)
+ (terminate-undotted-list n file))
+ (t
+ (sub-dump-object l file)
+ (terminate-dotted-list n file))))
(declare (type index n))
(let ((ref (gethash l circ)))
(when ref
- (push (make-circularity :type :rplacd
- :object list
- :index (1- n)
- :value l
- :enclosing-object ref)
- *circularities-detected*)
- (terminate-undotted-list n file)
- (return)))
+ (push (make-circularity :type :rplacd
+ :object list
+ :index (1- n)
+ :value l
+ :enclosing-object ref)
+ *circularities-detected*)
+ (terminate-undotted-list n file)
+ (return)))
(unless *cold-load-dump*
(setf (gethash l circ) list))
(let* ((obj (car l))
- (ref (gethash obj circ)))
+ (ref (gethash obj circ)))
(cond (ref
- (push (make-circularity :type :rplaca
- :object list
- :index n
- :value obj
- :enclosing-object ref)
- *circularities-detected*)
- (sub-dump-object nil file))
- (t
- (sub-dump-object obj file))))))
+ (push (make-circularity :type :rplaca
+ :object list
+ :index n
+ :value obj
+ :enclosing-object ref)
+ *circularities-detected*)
+ (sub-dump-object nil file))
+ (t
+ (sub-dump-object obj file))))))
(defun terminate-dotted-list (n file)
(declare (type index n) (type fasl-output file))
(6 (dump-fop 'fop-list*-6 file))
(7 (dump-fop 'fop-list*-7 file))
(8 (dump-fop 'fop-list*-8 file))
- (T (do ((nn n (- nn 255)))
- ((< nn 256)
- (dump-fop 'fop-list* file)
- (dump-byte nn file))
- (declare (type index nn))
- (dump-fop 'fop-list* file)
- (dump-byte 255 file)))))
+ (t (do ((nn n (- nn 255)))
+ ((< nn 256)
+ (dump-fop 'fop-list* file)
+ (dump-byte nn file))
+ (declare (type index nn))
+ (dump-fop 'fop-list* file)
+ (dump-byte 255 file)))))
;;; If N > 255, must build list with one LIST operator, then LIST*
;;; operators.
(6 (dump-fop 'fop-list-6 file))
(7 (dump-fop 'fop-list-7 file))
(8 (dump-fop 'fop-list-8 file))
- (T (cond ((< n 256)
- (dump-fop 'fop-list file)
- (dump-byte n file))
- (t (dump-fop 'fop-list file)
- (dump-byte 255 file)
- (do ((nn (- n 255) (- nn 255)))
- ((< nn 256)
- (dump-fop 'fop-list* file)
- (dump-byte nn file))
- (declare (type index nn))
- (dump-fop 'fop-list* file)
- (dump-byte 255 file)))))))
+ (t (cond ((< n 256)
+ (dump-fop 'fop-list file)
+ (dump-byte n file))
+ (t (dump-fop 'fop-list file)
+ (dump-byte 255 file)
+ (do ((nn (- n 255) (- nn 255)))
+ ((< nn 256)
+ (dump-fop 'fop-list* file)
+ (dump-byte nn file))
+ (declare (type index nn))
+ (dump-fop 'fop-list* file)
+ (dump-byte 255 file)))))))
\f
;;;; array dumping
;;; tables.
(defun dump-vector (x file)
(let ((simple-version (if (array-header-p x)
- (coerce x `(simple-array
- ,(array-element-type x)
- (*)))
- x)))
+ (coerce x `(simple-array
+ ,(array-element-type x)
+ (*)))
+ x)))
(typecase simple-version
+ #+sb-xc-host
+ (simple-string
+ (unless (string-check-table x file)
+ (dump-simple-base-string simple-version file)
+ (string-save-object x file)))
+ #-sb-xc-host
(simple-base-string
- (unless (equal-check-table x file)
- (dump-simple-string simple-version file)
- (equal-save-object x file)))
+ (unless (string-check-table x file)
+ (dump-simple-base-string simple-version file)
+ (string-save-object x file)))
+ #-sb-xc-host
+ ((simple-array character (*))
+ #!+sb-unicode
+ (unless (string-check-table x file)
+ (dump-simple-character-string simple-version file)
+ (string-save-object x file))
+ #!-sb-unicode
+ (bug "how did we get here?"))
(simple-vector
(dump-simple-vector simple-version file)
(eq-save-object x file))
((= index length)
(dump-fop* length fop-small-vector fop-vector file))
(let* ((obj (aref v index))
- (ref (gethash obj circ)))
+ (ref (gethash obj circ)))
(cond (ref
- (push (make-circularity :type :svset
- :object v
- :index index
- :value obj
- :enclosing-object ref)
- *circularities-detected*)
- (sub-dump-object nil file))
- (t
- (sub-dump-object obj file))))))
+ (push (make-circularity :type :svset
+ :object v
+ :index index
+ :value obj
+ :enclosing-object ref)
+ *circularities-detected*)
+ (sub-dump-object nil file))
+ (t
+ (sub-dump-object obj file))))))
;;; In the grand scheme of things I don't pretend to understand any
;;; more how this works, or indeed whether. But to write out specialized
(declare (type (simple-array * (*)) vec))
(let ((len (length vec)))
(labels ((dump-unsigned-vector (size bytes)
- (unless data-only
- (dump-fop 'fop-int-vector file)
- (dump-word len file)
- (dump-byte size file))
- ;; The case which is easy to handle in a portable way is when
- ;; the element size is a multiple of the output byte size, and
- ;; happily that's the only case we need to be portable. (The
- ;; cross-compiler has to output debug information (including
- ;; (SIMPLE-ARRAY (UNSIGNED-BYTE 8) *).) The other cases are only
- ;; needed in the target SBCL, so we let them be handled with
- ;; unportable bit bashing.
- (cond ((>= size 7) ; easy cases
- (multiple-value-bind (floor rem) (floor size 8)
- (aver (or (zerop rem) (= rem 7)))
- (when (= rem 7)
- (setq size (1+ size))
- (setq floor (1+ floor)))
- (dovector (i vec)
- (dump-integer-as-n-bytes
- (ecase sb!c:*backend-byte-order*
- (:little-endian i)
- (:big-endian (octet-swap i size)))
- floor file))))
- (t ; harder cases, not supported in cross-compiler
- (dump-raw-bytes vec bytes file))))
- (dump-signed-vector (size bytes)
- ;; Note: Dumping specialized signed vectors isn't
- ;; supported in the cross-compiler. (All cases here end
- ;; up trying to call DUMP-RAW-BYTES, which isn't
- ;; provided in the cross-compilation host, only on the
- ;; target machine.)
- (unless data-only
- (dump-fop 'fop-signed-int-vector file)
- (dump-word len file)
- (dump-byte size file))
- (dump-raw-bytes vec bytes file)))
+ (unless data-only
+ (dump-fop 'fop-int-vector file)
+ (dump-word len file)
+ (dump-byte size file))
+ ;; The case which is easy to handle in a portable way is when
+ ;; the element size is a multiple of the output byte size, and
+ ;; happily that's the only case we need to be portable. (The
+ ;; cross-compiler has to output debug information (including
+ ;; (SIMPLE-ARRAY (UNSIGNED-BYTE 8) *).) The other cases are only
+ ;; needed in the target SBCL, so we let them be handled with
+ ;; unportable bit bashing.
+ (cond ((>= size 7) ; easy cases
+ (multiple-value-bind (floor rem) (floor size 8)
+ (aver (or (zerop rem) (= rem 7)))
+ (when (= rem 7)
+ (setq size (1+ size))
+ (setq floor (1+ floor)))
+ (dovector (i vec)
+ (dump-integer-as-n-bytes
+ (ecase sb!c:*backend-byte-order*
+ (:little-endian i)
+ (:big-endian (octet-swap i size)))
+ floor file))))
+ (t ; harder cases, not supported in cross-compiler
+ (dump-raw-bytes vec bytes file))))
+ (dump-signed-vector (size bytes)
+ ;; Note: Dumping specialized signed vectors isn't
+ ;; supported in the cross-compiler. (All cases here end
+ ;; up trying to call DUMP-RAW-BYTES, which isn't
+ ;; provided in the cross-compilation host, only on the
+ ;; target machine.)
+ (unless data-only
+ (dump-fop 'fop-signed-int-vector file)
+ (dump-word len file)
+ (dump-byte size file))
+ (dump-raw-bytes vec bytes file)))
(etypecase vec
- #-sb-xc-host
- ((simple-array nil (*))
- (dump-unsigned-vector 0 0))
- (simple-bit-vector
- (dump-unsigned-vector 1 (ceiling len 8))) ; bits to bytes
- ;; KLUDGE: This isn't the best way of expressing that the host
- ;; may not have specializations for (unsigned-byte 2) and
- ;; (unsigned-byte 4), which means that these types are
- ;; type-equivalent to (simple-array (unsigned-byte 8) (*));
- ;; the workaround is to remove them from the etypecase, since
- ;; they can't be dumped from the cross-compiler anyway. --
- ;; CSR, 2002-05-07
- #-sb-xc-host
- ((simple-array (unsigned-byte 2) (*))
- (dump-unsigned-vector 2 (ceiling (ash len 1) 8))) ; bits to bytes
- #-sb-xc-host
- ((simple-array (unsigned-byte 4) (*))
- (dump-unsigned-vector 4 (ceiling (ash len 2) 8))) ; bits to bytes
- #-sb-xc-host
- ((simple-array (unsigned-byte 7) (*))
- (dump-unsigned-vector 7 len))
- ((simple-array (unsigned-byte 8) (*))
- (dump-unsigned-vector 8 len))
- #-sb-xc-host
- ((simple-array (unsigned-byte 15) (*))
- (dump-unsigned-vector 15 (* 2 len)))
- ((simple-array (unsigned-byte 16) (*))
- (dump-unsigned-vector 16 (* 2 len)))
- #-sb-xc-host
- ((simple-array (unsigned-byte 31) (*))
- (dump-unsigned-vector 31 (* 4 len)))
- ((simple-array (unsigned-byte 32) (*))
- (dump-unsigned-vector 32 (* 4 len)))
+ #-sb-xc-host
+ ((simple-array nil (*))
+ (dump-unsigned-vector 0 0))
+ (simple-bit-vector
+ (dump-unsigned-vector 1 (ceiling len 8))) ; bits to bytes
+ ;; KLUDGE: This isn't the best way of expressing that the host
+ ;; may not have specializations for (unsigned-byte 2) and
+ ;; (unsigned-byte 4), which means that these types are
+ ;; type-equivalent to (simple-array (unsigned-byte 8) (*));
+ ;; the workaround is to remove them from the etypecase, since
+ ;; they can't be dumped from the cross-compiler anyway. --
+ ;; CSR, 2002-05-07
+ #-sb-xc-host
+ ((simple-array (unsigned-byte 2) (*))
+ (dump-unsigned-vector 2 (ceiling (ash len 1) 8))) ; bits to bytes
+ #-sb-xc-host
+ ((simple-array (unsigned-byte 4) (*))
+ (dump-unsigned-vector 4 (ceiling (ash len 2) 8))) ; bits to bytes
+ #-sb-xc-host
+ ((simple-array (unsigned-byte 7) (*))
+ (dump-unsigned-vector 7 len))
+ ((simple-array (unsigned-byte 8) (*))
+ (dump-unsigned-vector 8 len))
+ #-sb-xc-host
+ ((simple-array (unsigned-byte 15) (*))
+ (dump-unsigned-vector 15 (* 2 len)))
+ ((simple-array (unsigned-byte 16) (*))
+ (dump-unsigned-vector 16 (* 2 len)))
+ #-sb-xc-host
+ ((simple-array (unsigned-byte 31) (*))
+ (dump-unsigned-vector 31 (* 4 len)))
+ ((simple-array (unsigned-byte 32) (*))
+ (dump-unsigned-vector 32 (* 4 len)))
#-sb-xc-host
#!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- ((simple-array (unsigned-byte-63) (*))
+ ((simple-array (unsigned-byte 63) (*))
(dump-unsigned-vector 63 (* 8 len)))
#!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- ((simple-array (unsigned-byte-64) (*))
+ ((simple-array (unsigned-byte 64) (*))
(dump-unsigned-vector 64 (* 8 len)))
- ((simple-array (signed-byte 8) (*))
- (dump-signed-vector 8 len))
- ((simple-array (signed-byte 16) (*))
- (dump-signed-vector 16 (* 2 len)))
+ ((simple-array (signed-byte 8) (*))
+ (dump-signed-vector 8 len))
+ ((simple-array (signed-byte 16) (*))
+ (dump-signed-vector 16 (* 2 len)))
#!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or))
- ((simple-array (unsigned-byte 29) (*))
- (dump-signed-vector 29 (* 4 len)))
+ ((simple-array (unsigned-byte 29) (*))
+ (dump-signed-vector 29 (* 4 len)))
#!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or))
- ((simple-array (signed-byte 30) (*))
- (dump-signed-vector 30 (* 4 len)))
- ((simple-array (signed-byte 32) (*))
- (dump-signed-vector 32 (* 4 len)))
+ ((simple-array (signed-byte 30) (*))
+ (dump-signed-vector 30 (* 4 len)))
+ ((simple-array (signed-byte 32) (*))
+ (dump-signed-vector 32 (* 4 len)))
#!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
((simple-array (unsigned-byte 60) (*))
(dump-signed-vector 60 (* 8 len)))
\f
;;; Dump characters and string-ish things.
-(defun dump-character (ch file)
- (dump-fop 'fop-short-character file)
- (dump-byte (char-code ch) file))
+(defun dump-character (char file)
+ (let ((code (sb!xc:char-code char)))
+ (cond
+ ((< code 256)
+ (dump-fop 'fop-short-character file)
+ (dump-byte code file))
+ (t
+ (dump-fop 'fop-character file)
+ (dump-word code file)))))
-;;; a helper function shared by DUMP-SIMPLE-STRING and DUMP-SYMBOL
-(defun dump-characters-of-string (s fasl-output)
- (declare (type string s) (type fasl-output fasl-output))
+(defun dump-base-chars-of-string (s fasl-output)
+ (declare #+sb-xc-host (type simple-string s)
+ #-sb-xc-host (type simple-base-string s)
+ (type fasl-output fasl-output))
(dovector (c s)
- (dump-byte (char-code c) fasl-output))
+ (dump-byte (sb!xc:char-code c) fasl-output))
(values))
+
;;; Dump a SIMPLE-BASE-STRING.
-;;; FIXME: should be called DUMP-SIMPLE-BASE-STRING then
-(defun dump-simple-string (s file)
- (declare (type simple-base-string s))
- (dump-fop* (length s) fop-small-string fop-string file)
- (dump-characters-of-string s file)
+(defun dump-simple-base-string (s file)
+ #+sb-xc-host (declare (type simple-string s))
+ #-sb-xc-host (declare (type simple-base-string s))
+ (dump-fop* (length s) fop-small-base-string fop-base-string file)
+ (dump-base-chars-of-string s file)
(values))
;;; If we get here, it is assumed that the symbol isn't in the table,
(defun dump-symbol (s file)
(declare (type fasl-output file))
(let* ((pname (symbol-name s))
- (pname-length (length pname))
- (pkg (symbol-package s)))
+ (pname-length (length pname))
+ (pkg (symbol-package s)))
(cond ((null pkg)
- (dump-fop* pname-length
- fop-uninterned-small-symbol-save
- fop-uninterned-symbol-save
- file))
- ;; CMU CL had FOP-SYMBOL-SAVE/FOP-SMALL-SYMBOL-SAVE fops which
- ;; used the current value of *PACKAGE*. Unfortunately that's
- ;; broken w.r.t. ANSI Common Lisp semantics, so those are gone
- ;; from SBCL.
- ;;((eq pkg *package*)
- ;; (dump-fop* pname-length
- ;; fop-small-symbol-save
- ;; fop-symbol-save file))
- ((eq pkg sb!int:*cl-package*)
- (dump-fop* pname-length
- fop-lisp-small-symbol-save
- fop-lisp-symbol-save
- file))
- ((eq pkg sb!int:*keyword-package*)
- (dump-fop* pname-length
- fop-keyword-small-symbol-save
- fop-keyword-symbol-save
- file))
- ((< pname-length 256)
- (dump-fop* (dump-package pkg file)
- fop-small-symbol-in-byte-package-save
- fop-small-symbol-in-package-save
- file)
- (dump-byte pname-length file))
- (t
- (dump-fop* (dump-package pkg file)
- fop-symbol-in-byte-package-save
- fop-symbol-in-package-save
- file)
- (dump-word pname-length file)))
-
- (dump-characters-of-string pname file)
+ (dump-fop* pname-length
+ fop-uninterned-small-symbol-save
+ fop-uninterned-symbol-save
+ file))
+ ;; CMU CL had FOP-SYMBOL-SAVE/FOP-SMALL-SYMBOL-SAVE fops which
+ ;; used the current value of *PACKAGE*. Unfortunately that's
+ ;; broken w.r.t. ANSI Common Lisp semantics, so those are gone
+ ;; from SBCL.
+ ;;((eq pkg *package*)
+ ;; (dump-fop* pname-length
+ ;; fop-small-symbol-save
+ ;; fop-symbol-save file))
+ ((eq pkg sb!int:*cl-package*)
+ (dump-fop* pname-length
+ fop-lisp-small-symbol-save
+ fop-lisp-symbol-save
+ file))
+ ((eq pkg sb!int:*keyword-package*)
+ (dump-fop* pname-length
+ fop-keyword-small-symbol-save
+ fop-keyword-symbol-save
+ file))
+ ((< pname-length 256)
+ (dump-fop* (dump-package pkg file)
+ fop-small-symbol-in-byte-package-save
+ fop-small-symbol-in-package-save
+ file)
+ (dump-byte pname-length file))
+ (t
+ (dump-fop* (dump-package pkg file)
+ fop-symbol-in-byte-package-save
+ fop-symbol-in-package-save
+ file)
+ (dump-word pname-length file)))
+
+ #+sb-xc-host (dump-base-chars-of-string pname file)
+ #-sb-xc-host (#!+sb-unicode dump-characters-of-string
+ #!-sb-unicode dump-base-chars-of-string
+ pname file)
(unless *cold-load-dump*
(setf (gethash s (fasl-output-eq-table file))
- (fasl-output-table-free file)))
+ (fasl-output-table-free file)))
(incf (fasl-output-table-free file)))
(defun dump-segment (segment code-length fasl-output)
(declare (type sb!assem:segment segment)
- (type fasl-output fasl-output))
+ (type fasl-output fasl-output))
(let* ((stream (fasl-output-stream fasl-output))
- (n-written (write-segment-contents segment stream)))
+ (n-written (write-segment-contents segment stream)))
;; In CMU CL there was no enforced connection between the CODE-LENGTH
;; argument and the number of bytes actually written. I added this
;; assertion while trying to debug portable genesis. -- WHN 19990902
(declare (list fixups) (type fasl-output fasl-output))
(dolist (note fixups)
(let* ((kind (fixup-note-kind note))
- (fixup (fixup-note-fixup note))
- (position (fixup-note-position note))
- (name (fixup-name fixup))
- (flavor (fixup-flavor fixup)))
+ (fixup (fixup-note-fixup note))
+ (position (fixup-note-position note))
+ (name (fixup-name fixup))
+ (flavor (fixup-flavor fixup)))
(dump-fop 'fop-normal-load fasl-output)
(let ((*cold-load-dump* t))
- (dump-object kind fasl-output))
+ (dump-object kind fasl-output))
(dump-fop 'fop-maybe-cold-load fasl-output)
;; Depending on the flavor, we may have various kinds of
;; noise before the position.
(ecase flavor
- (:assembly-routine
- (aver (symbolp name))
- (dump-fop 'fop-normal-load fasl-output)
- (let ((*cold-load-dump* t))
- (dump-object name fasl-output))
- (dump-fop 'fop-maybe-cold-load fasl-output)
- (dump-fop 'fop-assembler-fixup fasl-output))
- ((:foreign :foreign-dataref)
- (aver (stringp name))
- (ecase flavor
- (:foreign
- (dump-fop 'fop-foreign-fixup fasl-output))
- #!+linkage-table
- (:foreign-dataref
- (dump-fop 'fop-foreign-dataref-fixup fasl-output)))
- (let ((len (length name)))
- (aver (< len 256)) ; (limit imposed by fop definition)
- (dump-byte len fasl-output)
- (dotimes (i len)
- (dump-byte (char-code (schar name i)) fasl-output))))
- (:code-object
- (aver (null name))
- (dump-fop 'fop-code-object-fixup fasl-output)))
+ (:assembly-routine
+ (aver (symbolp name))
+ (dump-fop 'fop-normal-load fasl-output)
+ (let ((*cold-load-dump* t))
+ (dump-object name fasl-output))
+ (dump-fop 'fop-maybe-cold-load fasl-output)
+ (dump-fop 'fop-assembler-fixup fasl-output))
+ ((:foreign :foreign-dataref)
+ (aver (stringp name))
+ (ecase flavor
+ (:foreign
+ (dump-fop 'fop-foreign-fixup fasl-output))
+ #!+linkage-table
+ (:foreign-dataref
+ (dump-fop 'fop-foreign-dataref-fixup fasl-output)))
+ (let ((len (length name)))
+ (aver (< len 256)) ; (limit imposed by fop definition)
+ (dump-byte len fasl-output)
+ (dotimes (i len)
+ (dump-byte (char-code (schar name i)) fasl-output))))
+ (:code-object
+ (aver (null name))
+ (dump-fop 'fop-code-object-fixup fasl-output)))
;; No matter what the flavor, we'll always dump the position
(dump-word position fasl-output)))
(values))
;;;
;;; We dump trap objects in any unused slots or forward referenced slots.
(defun dump-code-object (component
- code-segment
- code-length
- trace-table-as-list
- fixups
- fasl-output)
+ code-segment
+ code-length
+ trace-table-as-list
+ fixups
+ fasl-output)
(declare (type component component)
- (list trace-table-as-list)
- (type index code-length)
- (type fasl-output fasl-output))
+ (list trace-table-as-list)
+ (type index code-length)
+ (type fasl-output fasl-output))
(let* ((2comp (component-info component))
- (constants (sb!c::ir2-component-constants 2comp))
- (header-length (length constants))
- (packed-trace-table (pack-trace-table trace-table-as-list))
- (total-length (+ code-length
- (* (length packed-trace-table)
- sb!c::tt-bytes-per-entry))))
+ (constants (sb!c::ir2-component-constants 2comp))
+ (header-length (length constants))
+ (packed-trace-table (pack-trace-table trace-table-as-list))
+ (total-length (+ code-length
+ (* (length packed-trace-table)
+ sb!c::tt-bytes-per-entry))))
(collect ((patches))
;; Dump the constants, noting any :ENTRY constants that have to
;; be patched.
(loop for i from sb!vm:code-constants-offset below header-length do
- (let ((entry (aref constants i)))
- (etypecase entry
- (constant
- (dump-object (sb!c::constant-value entry) fasl-output))
- (cons
- (ecase (car entry)
- (:entry
- (let* ((info (sb!c::leaf-info (cdr entry)))
- (handle (gethash info
- (fasl-output-entry-table
- fasl-output))))
- (declare (type sb!c::entry-info info))
- (cond
- (handle
- (dump-push handle fasl-output))
- (t
- (patches (cons info i))
- (dump-fop 'fop-misc-trap fasl-output)))))
- (:load-time-value
- (dump-push (cdr entry) fasl-output))
- (:fdefinition
- (dump-object (cdr entry) fasl-output)
- (dump-fop 'fop-fdefinition fasl-output))))
- (null
- (dump-fop 'fop-misc-trap fasl-output)))))
+ (let ((entry (aref constants i)))
+ (etypecase entry
+ (constant
+ (dump-object (sb!c::constant-value entry) fasl-output))
+ (cons
+ (ecase (car entry)
+ (:entry
+ (let* ((info (sb!c::leaf-info (cdr entry)))
+ (handle (gethash info
+ (fasl-output-entry-table
+ fasl-output))))
+ (declare (type sb!c::entry-info info))
+ (cond
+ (handle
+ (dump-push handle fasl-output))
+ (t
+ (patches (cons info i))
+ (dump-fop 'fop-misc-trap fasl-output)))))
+ (:load-time-value
+ (dump-push (cdr entry) fasl-output))
+ (:fdefinition
+ (dump-object (cdr entry) fasl-output)
+ (dump-fop 'fop-fdefinition fasl-output))))
+ (null
+ (dump-fop 'fop-misc-trap fasl-output)))))
;; Dump the debug info.
(let ((info (sb!c::debug-info-for-component component))
- (*dump-only-valid-structures* nil))
- (dump-object info fasl-output)
- (let ((info-handle (dump-pop fasl-output)))
- (dump-push info-handle fasl-output)
- (push info-handle (fasl-output-debug-info fasl-output))))
+ (*dump-only-valid-structures* nil))
+ (dump-object info fasl-output)
+ (let ((info-handle (dump-pop fasl-output)))
+ (dump-push info-handle fasl-output)
+ (push info-handle (fasl-output-debug-info fasl-output))))
(let ((num-consts (- header-length sb!vm:code-trace-table-offset-slot)))
- (cond ((and (< num-consts #x100) (< total-length #x10000))
- (dump-fop 'fop-small-code fasl-output)
- (dump-byte num-consts fasl-output)
- (dump-integer-as-n-bytes total-length (/ sb!vm:n-word-bytes 2) fasl-output))
- (t
- (dump-fop 'fop-code fasl-output)
- (dump-word num-consts fasl-output)
- (dump-word total-length fasl-output))))
+ (cond ((and (< num-consts #x100) (< total-length #x10000))
+ (dump-fop 'fop-small-code fasl-output)
+ (dump-byte num-consts fasl-output)
+ (dump-integer-as-n-bytes total-length (/ sb!vm:n-word-bytes 2) fasl-output))
+ (t
+ (dump-fop 'fop-code fasl-output)
+ (dump-word num-consts fasl-output)
+ (dump-word total-length fasl-output))))
;; These two dumps are only ones which contribute to our
;; TOTAL-LENGTH value.
(dump-fop 'fop-sanctify-for-execution fasl-output)
(let ((handle (dump-pop fasl-output)))
- (dolist (patch (patches))
- (push (cons handle (cdr patch))
- (gethash (car patch)
- (fasl-output-patch-table fasl-output))))
- handle))))
+ (dolist (patch (patches))
+ (push (cons handle (cdr patch))
+ (gethash (car patch)
+ (fasl-output-patch-table fasl-output))))
+ handle))))
(defun dump-assembler-routines (code-segment length fixups routines file)
(dump-fop 'fop-assembler-code file)
;;; component.
(defun dump-one-entry (entry code-handle file)
(declare (type sb!c::entry-info entry) (type index code-handle)
- (type fasl-output file))
+ (type fasl-output file))
(let ((name (sb!c::entry-info-name entry)))
(dump-push code-handle file)
(dump-object name file)
;;; Dump the code, constants, etc. for component. We pass in the
;;; assembler fixups, code vector and node info.
(defun fasl-dump-component (component
- code-segment
- code-length
- trace-table
- fixups
- file)
+ code-segment
+ code-length
+ trace-table
+ fixups
+ file)
(declare (type component component) (list trace-table))
(declare (type fasl-output file))
- (dump-fop 'fop-verify-empty-stack file)
(dump-fop 'fop-verify-table-size file)
(dump-word (fasl-output-table-free file) file)
(fasl-validate-structure info file)))
(let ((code-handle (dump-code-object component
- code-segment
- code-length
- trace-table
- fixups
- file))
- (2comp (component-info component)))
- (dump-fop 'fop-verify-empty-stack file)
+ code-segment
+ code-length
+ trace-table
+ fixups
+ file))
+ (2comp (component-info component)))
(dolist (entry (sb!c::ir2-component-entries 2comp))
(let ((entry-handle (dump-one-entry entry code-handle file)))
- (setf (gethash entry (fasl-output-entry-table file)) entry-handle)
- (let ((old (gethash entry (fasl-output-patch-table file))))
- (when old
- (dolist (patch old)
- (dump-alter-code-object (car patch)
- (cdr patch)
- entry-handle
- file))
- (remhash entry (fasl-output-patch-table file)))))))
+ (setf (gethash entry (fasl-output-entry-table file)) entry-handle)
+ (let ((old (gethash entry (fasl-output-patch-table file))))
+ (when old
+ (dolist (patch old)
+ (dump-alter-code-object (car patch)
+ (cdr patch)
+ entry-handle
+ file))
+ (remhash entry (fasl-output-patch-table file)))))))
(values))
(defun dump-push-previously-dumped-fun (fun fasl-output)
(declare (type sb!c::clambda fun))
(let ((handle (gethash (sb!c::leaf-info fun)
- (fasl-output-entry-table fasl-output))))
+ (fasl-output-entry-table fasl-output))))
(aver handle)
(dump-push handle fasl-output))
(values))
(dump-push fun-dump-handle fasl-output)
(dump-fop 'fop-fset fasl-output)
(values))
-
+
;;; Compute the correct list of DEBUG-SOURCE structures and backpatch
;;; all of the dumped DEBUG-INFO structures. We clear the
;;; FASL-OUTPUT-DEBUG-INFO, so that subsequent components with
(defun fasl-dump-source-info (info fasl-output)
(declare (type sb!c::source-info info))
(let ((res (sb!c::debug-source-for-info info))
- (*dump-only-valid-structures* nil))
+ (*dump-only-valid-structures* nil))
(dump-object res fasl-output)
(let ((res-handle (dump-pop fasl-output)))
(dolist (info-handle (fasl-output-debug-info fasl-output))
- (dump-push res-handle fasl-output)
- (dump-fop 'fop-structset fasl-output)
- (dump-word info-handle fasl-output)
+ (dump-push res-handle fasl-output)
+ (dump-fop 'fop-structset fasl-output)
+ (dump-word info-handle fasl-output)
;; FIXME: what is this bare `2'? --njf, 2004-08-16
- (dump-word 2 fasl-output))))
+ (dump-word 2 fasl-output))))
(setf (fasl-output-debug-info fasl-output) nil)
(values))
\f
(when *dump-only-valid-structures*
(unless (gethash struct (fasl-output-valid-structures file))
(error "attempt to dump invalid structure:~% ~S~%How did this happen?"
- struct)))
+ struct)))
(note-potential-circularity struct file)
- (do ((index 0 (1+ index))
- (length (%instance-length struct))
- (circ (fasl-output-circularity-table file)))
- ((= index length)
+ (aver (%instance-ref struct 0))
+ (do* ((length (%instance-length struct))
+ (ntagged (- length (layout-n-untagged-slots (%instance-ref struct 0))))
+ (circ (fasl-output-circularity-table file))
+ ;; last slot first on the stack, so that the layout is on top:
+ (index (1- length) (1- index)))
+ ((minusp index)
(dump-fop* length fop-small-struct fop-struct file))
- (let* ((obj (%instance-ref struct index))
- (ref (gethash obj circ)))
+ (let* ((obj (if (>= index ntagged)
+ (%raw-instance-ref/word struct (- length index 1))
+ (%instance-ref struct index)))
+ (ref (gethash obj circ)))
(cond (ref
- (push (make-circularity :type :struct-set
- :object struct
- :index index
- :value obj
- :enclosing-object ref)
- *circularities-detected*)
- (sub-dump-object nil file))
- (t
- (sub-dump-object obj file))))))
+ (aver (not (zerop index)))
+ (push (make-circularity :type :struct-set
+ :object struct
+ :index index
+ :value obj
+ :enclosing-object ref)
+ *circularities-detected*)
+ (sub-dump-object nil file))
+ (t
+ (sub-dump-object obj file))))))
(defun dump-layout (obj file)
(when (layout-invalid obj)
(compiler-error "attempt to dump reference to obsolete class: ~S"
- (layout-classoid obj)))
+ (layout-classoid obj)))
(let ((name (classoid-name (layout-classoid obj))))
(unless name
(compiler-error "dumping anonymous layout: ~S" obj))
(sub-dump-object (layout-inherits obj) file)
(sub-dump-object (layout-depthoid obj) file)
(sub-dump-object (layout-length obj) file)
+ (sub-dump-object (layout-n-untagged-slots obj) file)
(dump-fop 'fop-layout file))