X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fdump.lisp;h=ede2e77dac18c5318f81518574c4d854bd780c4c;hb=bf27595fb567015495b7131707cc85af361567fe;hp=7c4619f02391bdaf272129bbf3658e5d664886fa;hpb=5930ee54090c03d242c70716683b12b95d74a089;p=sbcl.git diff --git a/src/compiler/dump.lisp b/src/compiler/dump.lisp index 7c4619f..ede2e77 100644 --- a/src/compiler/dump.lisp +++ b/src/compiler/dump.lisp @@ -33,7 +33,7 @@ ;; can get them from the table rather than dumping them again. The ;; EQUAL-TABLE is used for lists and strings, and the EQ-TABLE is ;; used for everything else. We use a separate EQ table to avoid - ;; performance patholigies with objects for which EQUAL degnerates + ;; performance pathologies with objects for which EQUAL degenerates ;; to EQL. Everything entered in the EQUAL table is also entered in ;; the EQ table. (equal-table (make-hash-table :test 'equal) :type hash-table) @@ -105,12 +105,12 @@ (declare (type (unsigned-byte 8) b) (type fasl-output fasl-output)) (write-byte b (fasl-output-stream fasl-output))) -;;; Dump a 4 byte unsigned integer. -(defun dump-unsigned-32 (num fasl-output) - (declare (type (unsigned-byte 32) num)) +;; Dump a word-sized integer. +(defun dump-word (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) + (dotimes (i sb!vm:n-word-bytes) (write-byte (ldb (byte 8 (* 8 i)) num) stream)))) ;;; Dump NUM to the fasl stream, represented by N bytes. This works @@ -151,7 +151,8 @@ #!+sb-show (when *fop-nop4-count* (dump-byte ,(get 'fop-nop4 'fop-code) ,file) - (dump-unsigned-32 (mod (incf *fop-nop4-count*) (expt 2 32)) ,file)) + (dump-integer-as-n-bytes (mod (incf *fop-nop4-count*) (expt 2 32)) + 4 ,file)) (dump-byte ',val ,file)) (error "compiler bug: ~S is not a legal fasload operator." fs)))) @@ -168,7 +169,7 @@ (dump-byte ,n-n ,n-file)) (t (dump-fop ',word-fop ,n-file) - (dump-unsigned-32 ,n-n ,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) @@ -191,11 +192,19 @@ (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 @@ -216,7 +225,16 @@ (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. @@ -279,28 +297,30 @@ ;; character code. (fasl-write-string (with-standard-io-syntax - (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))) + (let ((*print-readably* 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)))) 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-unsigned-32 (length string) res) + (dump-word (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-unsigned-32 +fasl-file-version+ res) + (dump-word +fasl-file-version+ res) (dump-counted-string *features-affecting-fasl-format*)) res)) @@ -315,7 +335,7 @@ ;; End the group. (dump-fop 'fop-verify-empty-stack fasl-output) (dump-fop 'fop-verify-table-size fasl-output) - (dump-unsigned-32 (fasl-output-table-free fasl-output) + (dump-word (fasl-output-table-free fasl-output) fasl-output) (dump-fop 'fop-end-group fasl-output) @@ -367,11 +387,8 @@ (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 (and its callees) are responsible for + ;; updating the EQ and EQUAL hash tables. (dump-array x file)) (number (unless (equal-check-table x file) @@ -390,7 +407,7 @@ ;;; Dump an object of any type by dispatching to the correct ;;; type-specific dumping function. We pick off immediate objects, -;;; symbols and and magic lists here. Other objects are handled by +;;; symbols and magic lists here. Other objects are handled by ;;; DUMP-NON-IMMEDIATE-OBJECT. ;;; ;;; This is the function used for recursive calls to the fasl dumper. @@ -427,7 +444,7 @@ (i 0 (1+ i))) ((eq current value) (dump-fop 'fop-nthcdr file) - (dump-unsigned-32 i file)) + (dump-word i file)) (declare (type index i))))) (ecase (circularity-type info) @@ -435,8 +452,8 @@ (:rplacd (dump-fop 'fop-rplacd file)) (:svset (dump-fop 'fop-svset file)) (:struct-set (dump-fop 'fop-structset file))) - (dump-unsigned-32 (gethash (circularity-object info) table) file) - (dump-unsigned-32 (circularity-index info) file)))) + (dump-word (gethash (circularity-object info) table) file) + (dump-word (circularity-index info) file)))) ;;; Set up stuff for circularity detection, then dump an object. All ;;; shared and circular structure will be exactly preserved within a @@ -507,12 +524,12 @@ ((signed-byte 8) (dump-fop 'fop-byte-integer file) (dump-byte (logand #xFF n) file)) - ((unsigned-byte 31) + ((unsigned-byte #.(1- sb!vm:n-word-bits)) (dump-fop 'fop-word-integer file) - (dump-unsigned-32 n file)) - ((signed-byte 32) + (dump-word n file)) + ((signed-byte #.sb!vm:n-word-bits) (dump-fop 'fop-word-integer file) - (dump-integer-as-n-bytes n 4 file)) + (dump-integer-as-n-bytes n #.sb!vm:n-word-bytes file)) (t (let ((bytes (ceiling (1+ (integer-length n)) 8))) (dump-fop* bytes fop-small-integer fop-integer file) @@ -527,9 +544,7 @@ (dump-fop 'fop-double-float file) (let ((x x)) (declare (double-float x)) - ;; FIXME: Why sometimes DUMP-UNSIGNED-32 and sometimes - ;; DUMP-INTEGER-AS-N-BYTES .. 4? - (dump-unsigned-32 (double-float-low-bits x) file) + (dump-integer-as-n-bytes (double-float-low-bits x) 4 file) (dump-integer-as-n-bytes (double-float-high-bits x) 4 file))) #!+long-float (long-float @@ -548,11 +563,11 @@ (dump-fop 'fop-complex-double-float file) (let ((re (realpart x))) (declare (double-float re)) - (dump-unsigned-32 (double-float-low-bits re) file) + (dump-integer-as-n-bytes (double-float-low-bits re) 4 file) (dump-integer-as-n-bytes (double-float-high-bits re) 4 file)) (let ((im (imagpart x))) (declare (double-float im)) - (dump-unsigned-32 (double-float-low-bits im) file) + (dump-integer-as-n-bytes (double-float-low-bits im) 4 file) (dump-integer-as-n-bytes (double-float-high-bits im) 4 file))) #!+long-float ((complex long-float) @@ -585,7 +600,15 @@ (t (unless *cold-load-dump* (dump-fop 'fop-normal-load file)) - (dump-simple-string (package-name pkg) 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)) @@ -716,10 +739,24 @@ (*))) 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)) @@ -789,7 +826,7 @@ (labels ((dump-unsigned-vector (size bytes) (unless data-only (dump-fop 'fop-int-vector file) - (dump-unsigned-32 len 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 @@ -798,9 +835,12 @@ ;; (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 8) ; easy cases + (cond ((>= size 7) ; easy cases (multiple-value-bind (floor rem) (floor size 8) - (aver (zerop rem)) + (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* @@ -817,13 +857,15 @@ ;; target machine.) (unless data-only (dump-fop 'fop-signed-int-vector file) - (dump-unsigned-32 len file) + (dump-word len file) (dump-byte size file)) (dump-raw-bytes vec bytes file))) (etypecase vec - ;; KLUDGE: What exactly does the (ASH .. -3) stuff do? -- WHN 19990902 + #-sb-xc-host + ((simple-array nil (*)) + (dump-unsigned-vector 0 0)) (simple-bit-vector - (dump-unsigned-vector 1 (ash (+ (the index len) 7) -3))) + (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 @@ -833,44 +875,81 @@ ;; CSR, 2002-05-07 #-sb-xc-host ((simple-array (unsigned-byte 2) (*)) - (dump-unsigned-vector 2 (ash (+ (the index (ash len 1)) 7) -3))) + (dump-unsigned-vector 2 (ceiling (ash len 1) 8))) ; bits to bytes #-sb-xc-host ((simple-array (unsigned-byte 4) (*)) - (dump-unsigned-vector 4 (ash (+ (the index (ash len 2)) 7) -3))) + (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) (*)) + (dump-unsigned-vector 63 (* 8 len))) + #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or)) + ((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))) + #!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or)) + ((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))))))) + (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))) + #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or)) + ((simple-array (signed-byte 61) (*)) + (dump-signed-vector 61 (* 8 len))) + #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or)) + ((simple-array (signed-byte 64) (*)) + (dump-signed-vector 64 (* 8 len))))))) ;;; Dump characters and string-ish things. -(defun dump-character (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 (char-code ch) 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, @@ -918,9 +997,12 @@ fop-symbol-in-byte-package-save fop-symbol-in-package-save file) - (dump-unsigned-32 pname-length file))) + (dump-word pname-length file))) - (dump-characters-of-string pname 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)) @@ -950,27 +1032,18 @@ ;;; - code object references: don't need a name. (defun dump-fixups (fixups fasl-output) (declare (list fixups) (type fasl-output fasl-output)) - (dolist (info fixups) - ;; FIXME: Packing data with LIST in NOTE-FIXUP and unpacking them - ;; with FIRST, SECOND, and THIRD here is hard to follow and - ;; maintain. Perhaps we could define a FIXUP-INFO structure to use - ;; instead, and rename *FIXUPS* to *FIXUP-INFO-LIST*? - (let* ((kind (first info)) - (fixup (second info)) + (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)) - (offset (third info))) - ;; FIXME: This OFFSET is not what's called OFFSET in the FIXUP - ;; structure, it's what's called POSN in NOTE-FIXUP. (As far as - ;; I can tell, FIXUP-OFFSET is not actually an offset, it's an - ;; internal label used instead of NAME for :CODE-OBJECT fixups. - ;; Notice that in the :CODE-OBJECT case, NAME is ignored.) + (flavor (fixup-flavor fixup))) (dump-fop 'fop-normal-load fasl-output) (let ((*cold-load-dump* t)) (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 offset. + ;; noise before the position. (ecase flavor (:assembly-routine (aver (symbolp name)) @@ -979,9 +1052,14 @@ (dump-object name fasl-output)) (dump-fop 'fop-maybe-cold-load fasl-output) (dump-fop 'fop-assembler-fixup fasl-output)) - (:foreign + ((:foreign :foreign-dataref) (aver (stringp name)) - (dump-fop 'fop-foreign-fixup fasl-output) + (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) @@ -990,8 +1068,8 @@ (:code-object (aver (null name)) (dump-fop 'fop-code-object-fixup fasl-output))) - ;; No matter what the flavor, we'll always dump the offset. - (dump-unsigned-32 offset fasl-output))) + ;; No matter what the flavor, we'll always dump the position + (dump-word position fasl-output))) (values)) ;;; Dump out the constant pool and code-vector for component, push the @@ -1034,6 +1112,8 @@ ;; hardwired to be empty. And SBCL doesn't have GENGC (and as ;; far as I know no modern CMU CL does either -- WHN ;; 2001-10-05). So might we be able to get rid of trace tables? + ;; + ;; Note that gencgc also does something with the trace table. ;; Dump the constants, noting any :ENTRY constants that have to ;; be patched. @@ -1076,11 +1156,11 @@ (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 2 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-unsigned-32 num-consts fasl-output) - (dump-unsigned-32 total-length 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. @@ -1103,7 +1183,7 @@ (defun dump-assembler-routines (code-segment length fixups routines file) (dump-fop 'fop-assembler-code file) - (dump-unsigned-32 length file) + (dump-word length file) (write-segment-contents code-segment (fasl-output-stream file)) (dolist (routine routines) (dump-fop 'fop-normal-load file) @@ -1111,7 +1191,7 @@ (dump-object (car routine) file)) (dump-fop 'fop-maybe-cold-load file) (dump-fop 'fop-assembler-routine file) - (dump-unsigned-32 (label-position (cdr routine)) file)) + (dump-word (label-position (cdr routine)) file)) (dump-fixups fixups file) (dump-fop 'fop-sanctify-for-execution file) (dump-pop file)) @@ -1128,7 +1208,7 @@ (dump-object (sb!c::entry-info-arguments entry) file) (dump-object (sb!c::entry-info-type entry) file) (dump-fop 'fop-fun-entry file) - (dump-unsigned-32 (label-position (sb!c::entry-info-offset entry)) file) + (dump-word (label-position (sb!c::entry-info-offset entry)) file) (dump-pop file))) ;;; Alter the code object referenced by CODE-HANDLE at the specified @@ -1154,7 +1234,7 @@ (dump-fop 'fop-verify-empty-stack file) (dump-fop 'fop-verify-table-size file) - (dump-unsigned-32 (fasl-output-table-free file) file) + (dump-word (fasl-output-table-free file) file) #!+sb-dyncount (let ((info (sb!c::ir2-component-dyncount-info (component-info component)))) @@ -1225,8 +1305,9 @@ (dolist (info-handle (fasl-output-debug-info fasl-output)) (dump-push res-handle fasl-output) (dump-fop 'fop-structset fasl-output) - (dump-unsigned-32 info-handle fasl-output) - (dump-unsigned-32 2 fasl-output)))) + (dump-word info-handle fasl-output) + ;; FIXME: what is this bare `2'? --njf, 2004-08-16 + (dump-word 2 fasl-output)))) (setf (fasl-output-debug-info fasl-output) nil) (values)) @@ -1259,7 +1340,7 @@ (defun dump-layout (obj file) (when (layout-invalid obj) (compiler-error "attempt to dump reference to obsolete class: ~S" - (layout-class obj))) + (layout-classoid obj))) (let ((name (classoid-name (layout-classoid obj)))) (unless name (compiler-error "dumping anonymous layout: ~S" obj))